home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Suzy B Software 2
/
Suzy B Software CD-ROM 2 (1994).iso
/
extras
/
programm
/
gemfsc19
/
gemfsc19.lzh
/
GEMFAST.DOC
< prev
next >
Wrap
Text File
|
1993-05-15
|
324KB
|
10,825 lines
GemFast v1.9 Beta
Public Domain GEM Programming Library
By Ian Lepore
Reference Manual
Contents
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Quick Start Info . . . . . . . . . . . . . . . . . . . . . . . 1
Using this document . . . . . . . . . . . . . . . . . . . . . 1
Begging for money . . . . . . . . . . . . . . . . . . . . . . 2
Support . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Function Quick-Reference . . . . . . . . . . . . . . . . . . . . 4
Global Variables . . . . . . . . . . . . . . . . . . . . . . . . 7
global[] . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_apversion . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_apcount . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_apid . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_apprivate . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_apptree . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_ap1resv . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_aprshdr . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_ap2resv . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_grfhandle . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_rwdesk . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_rfscrn . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_hchar . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_h2char . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_h4char . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_h8char . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_wchar . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_w2char . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_w4char . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_w8char . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_wbox . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_hbox . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_vwout . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
gl_vxout . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Application Library . . . . . . . . . . . . . . . . . . . . . . . 10
apl_cleanup . . . . . . . . . . . . . . . . . . . . . . . . . 11
apl_mmvectors . . . . . . . . . . . . . . . . . . . . . . . . 12
apl_vclose . . . . . . . . . . . . . . . . . . . . . . . . . . 13
apl_vopen . . . . . . . . . . . . . . . . . . . . . . . . . . 14
apl_vshared . . . . . . . . . . . . . . . . . . . . . . . . . 15
apl_xexit . . . . . . . . . . . . . . . . . . . . . . . . . . 16
appl_exit . . . . . . . . . . . . . . . . . . . . . . . . . . 16
apl_xinit . . . . . . . . . . . . . . . . . . . . . . . . . . 17
appl_init . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Error Message Library . . . . . . . . . . . . . . . . . . . . . . 18
exterror . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
exterrset . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Forms and Dialogs Library . . . . . . . . . . . . . . . . . . . . 22
Summary of Dialog Functions . . . . . . . . . . . . . . . . . 22
Dialog Processing Options . . . . . . . . . . . . . . . . . . 23
======================================================================
GemFast v1.8 Page i
Basic Dialog Options . . . . . . . . . . . . . . . . . . . 24
Dynamic Dialog Options . . . . . . . . . . . . . . . . . . 25
Dynamic Dialog Defaults . . . . . . . . . . . . . . . . . . 26
Text and Button Formatting in Dynamic Dialogs . . . . . . . . 26
frm_confine . . . . . . . . . . . . . . . . . . . . . . . . . 28
frm_defaults . . . . . . . . . . . . . . . . . . . . . . . . . 29
frm_desktop . . . . . . . . . . . . . . . . . . . . . . . . . 30
frm_dialog . . . . . . . . . . . . . . . . . . . . . . . . . . 32
frm_dsdial . . . . . . . . . . . . . . . . . . . . . . . . . . 35
frm_dsdialog . . . . . . . . . . . . . . . . . . . . . . . . . 35
frm_eflag . . . . . . . . . . . . . . . . . . . . . . . . . . 37
frm_enableblit . . . . . . . . . . . . . . . . . . . . . . . . 39
frm_error . . . . . . . . . . . . . . . . . . . . . . . . . . 40
frm_menu . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
frm_mkmoveable . . . . . . . . . . . . . . . . . . . . . . . . 43
frm_nldialog . . . . . . . . . . . . . . . . . . . . . . . . . 44
frm_nlmenu . . . . . . . . . . . . . . . . . . . . . . . . . . 45
frm_printf . . . . . . . . . . . . . . . . . . . . . . . . . . 46
frm_progress . . . . . . . . . . . . . . . . . . . . . . . . . 47
frm_qchoice . . . . . . . . . . . . . . . . . . . . . . . . . 50
frm_qerror . . . . . . . . . . . . . . . . . . . . . . . . . . 51
frm_qfatal . . . . . . . . . . . . . . . . . . . . . . . . . . 52
frm_qmenu . . . . . . . . . . . . . . . . . . . . . . . . . . 53
frm_qtext . . . . . . . . . . . . . . . . . . . . . . . . . . 54
frm_question . . . . . . . . . . . . . . . . . . . . . . . . . 55
frm_sizes . . . . . . . . . . . . . . . . . . . . . . . . . . 56
frm_verror . . . . . . . . . . . . . . . . . . . . . . . . . . 57
frm_vprintf . . . . . . . . . . . . . . . . . . . . . . . . . 57
frm_vprogres . . . . . . . . . . . . . . . . . . . . . . . . . 57
File Selector Library . . . . . . . . . . . . . . . . . . . . . . 58
fsel_exinput . . . . . . . . . . . . . . . . . . . . . . . . . 59
fsel_sminput . . . . . . . . . . . . . . . . . . . . . . . . . 60
fsl_dialog . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Graphics Library . . . . . . . . . . . . . . . . . . . . . . . . 64
gra_qmstate . . . . . . . . . . . . . . . . . . . . . . . . . 65
gra_qofmouse . . . . . . . . . . . . . . . . . . . . . . . . . 65
gra_qonmouse . . . . . . . . . . . . . . . . . . . . . . . . . 65
grf_blit . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
grf_memblit . . . . . . . . . . . . . . . . . . . . . . . . . 68
graf_mouse . . . . . . . . . . . . . . . . . . . . . . . . . . 69
grf_mouse . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Menu Library . . . . . . . . . . . . . . . . . . . . . . . . . . 71
menu_bar . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
mnu_bar . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
mnu_disable . . . . . . . . . . . . . . . . . . . . . . . . . 73
mnu_enable . . . . . . . . . . . . . . . . . . . . . . . . . . 74
mnu_erase . . . . . . . . . . . . . . . . . . . . . . . . . . 75
mnu_tbar . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Object Library . . . . . . . . . . . . . . . . . . . . . . . . . 77
obj_bmbuttons . . . . . . . . . . . . . . . . . . . . . . . . 78
======================================================================
GemFast v1.8 Page ii
obj_clcalc . . . . . . . . . . . . . . . . . . . . . . . . . . 81
obj_flchange . . . . . . . . . . . . . . . . . . . . . . . . . 82
obj_gstring . . . . . . . . . . . . . . . . . . . . . . . . . 83
obj_gtype . . . . . . . . . . . . . . . . . . . . . . . . . . 84
obj_gvalue . . . . . . . . . . . . . . . . . . . . . . . . . . 85
obj_offxywh . . . . . . . . . . . . . . . . . . . . . . . . . 86
obj_parent . . . . . . . . . . . . . . . . . . . . . . . . . . 87
obj_ppstring . . . . . . . . . . . . . . . . . . . . . . . . . 88
obj_rbfind . . . . . . . . . . . . . . . . . . . . . . . . . . 89
obj_rbselect . . . . . . . . . . . . . . . . . . . . . . . . . 90
obj_sstring . . . . . . . . . . . . . . . . . . . . . . . . . 91
obj_stchange . . . . . . . . . . . . . . . . . . . . . . . . . 92
obj_svalue . . . . . . . . . . . . . . . . . . . . . . . . . . 93
obj_xtfind . . . . . . . . . . . . . . . . . . . . . . . . . . 94
obj_xywh . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Miscellanious Utilities Library . . . . . . . . . . . . . . . . . 96
rc_confine . . . . . . . . . . . . . . . . . . . . . . . . . . 97
rc_copy . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
rc_equal . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
rc_gadjust . . . . . . . . . . . . . . . . . . . . . . . . . . 100
rc_gtov . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
rc_intersect . . . . . . . . . . . . . . . . . . . . . . . . . 102
rc_ptinrect . . . . . . . . . . . . . . . . . . . . . . . . . 103
rc_scale . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
rc_union . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
rc_vadjust . . . . . . . . . . . . . . . . . . . . . . . . . . 106
rc_vtog . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
RECTARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . 108
RECTPTRS . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
RECTVALS . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
wc_scroll_calc . . . . . . . . . . . . . . . . . . . . . . . . 111
Resource Library . . . . . . . . . . . . . . . . . . . . . . . . 112
rsc_cubuttons . . . . . . . . . . . . . . . . . . . . . . . . 113
rsc_gstrings . . . . . . . . . . . . . . . . . . . . . . . . . 114
rsc_gtrees . . . . . . . . . . . . . . . . . . . . . . . . . . 116
rsc_rrbuttons . . . . . . . . . . . . . . . . . . . . . . . . 117
rsc_sstrings . . . . . . . . . . . . . . . . . . . . . . . . . 118
rsc_sxtypes . . . . . . . . . . . . . . . . . . . . . . . . . 120
rsc_treefix . . . . . . . . . . . . . . . . . . . . . . . . . 121
Window Library . . . . . . . . . . . . . . . . . . . . . . . . . 122
wnd_top . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
wind_update . . . . . . . . . . . . . . . . . . . . . . . . . 124
wnd_update . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Extended Binding Functions . . . . . . . . . . . . . . . . . . . 125
evnx_multi . . . . . . . . . . . . . . . . . . . . . . . . . . 126
frmx_center . . . . . . . . . . . . . . . . . . . . . . . . . 127
frmx_dial . . . . . . . . . . . . . . . . . . . . . . . . . . 128
grfx_dragbox . . . . . . . . . . . . . . . . . . . . . . . . . 129
winx_calc . . . . . . . . . . . . . . . . . . . . . . . . . . 130
winx_get . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
======================================================================
GemFast v1.8 Page iii
Extended VDI Functions . . . . . . . . . . . . . . . . . . . . . 132
vdicall . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
vgd_detect . . . . . . . . . . . . . . . . . . . . . . . . . . 134
vg_gdos . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
v_gchar . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Extended Object Library . . . . . . . . . . . . . . . . . . . . . 136
Background . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Using Extended Objects . . . . . . . . . . . . . . . . . . . . 137
xob_nslide_change . . . . . . . . . . . . . . . . . . . . . . 139
xob_nslide_create . . . . . . . . . . . . . . . . . . . . . . 140
xob_nslide_get . . . . . . . . . . . . . . . . . . . . . . . . 142
xob_nslide_set . . . . . . . . . . . . . . . . . . . . . . . . 143
xob_thermo_change . . . . . . . . . . . . . . . . . . . . . . 144
xob_thermo_create . . . . . . . . . . . . . . . . . . . . . . 145
xob_thermo_update . . . . . . . . . . . . . . . . . . . . . . 147
xob_tscroll_create . . . . . . . . . . . . . . . . . . . . . . 149
xob_tscroll_get . . . . . . . . . . . . . . . . . . . . . . . 151
xob_tscroll_set . . . . . . . . . . . . . . . . . . . . . . . 152
Extended Object Developer's Guide . . . . . . . . . . . . . . . . 155
xob_draw . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
xob_transform . . . . . . . . . . . . . . . . . . . . . . . . 158
======================================================================
GemFast v1.8 Page iv
Introduction
Welcome to version 1.9 of GemFast, the public domain GEM
bindings and programming library.
The primary changes in v1.9 are concerned with portability
to most existing ST compilers. The source code and header
files now use ANSI function prototypes when the host
compiler supports them.
The other major change is the consistent use of 'short'
rather than 'int' in the GEM interface. This became an
issue with compilers (such as GNU C and Lattice C) that
support both 16-bit and 32-bit integer sizes. The Lattice C
compiler (which Atari itself now uses) has low-level GEM
bindings that use the 'short' datatype consistently, so
GemFast has adopted this convention. You may experience a
few pointer type mismatches if you're using an ANSI
compiler, but these are (in my experience anyway) quickly
fixed in your source code by changing int* to short*.
Quick Start Info
Because you generally only need it once, the installation
instructions, packing list, technical notes, and portability
notes are in a separate file called GEMFINST.DOC.
If you're installing for the first time, GEMFINST.DOC has
all the info you need to install the GemFast files on your
system. If you got GemFast along with the HSC compiler, the
INSTALL program has already installed GemFast for you, but
you should still review GEMFINST.DOC.
If you're upgrading from a prior release, you'll find the
installation process pretty much the same as usual.
Using this document
This document, as delivered, is formatted for printing on
virtually any printer. The format is a compromise between
one that prints reasonably well on any type of printer, and
one that is easy to browse interactively with an editor.
The original document is formatted very nicely indeed, in WP
5.1 (MSDOS) format. I'll distribute that version too, if
anyone asks for it.
Here are some hints for online viewing... If you're looking
for a particular function, do a search on its name. You'll
find the entry in the table of contents. If you just need a
======================================================================
GemFast v1.8 Page 1
reminder of the function parameters, do a 'repeat search',
and you'll find the prototype in the Quick Reference
chapter. If you want the full details of for the function,
note the page number when you find the function in the table
of contents, then do a search for "Page ##" to get near the
function. Then back up a few lines (page numbers are at the
bottom of each page) to find the function.
This rather complex search-for-the-page-number nonsense is
needed because the function descriptions include cross
references and you could end up doing 20 or 30 'repeat
search' operations on the function name to get to the actual
description. I hope to write a hypertext-like browser
accessory for these docs soon to make this problem go away.
In the function descriptions, the last item is always a line
stating where the source code for the file is found.
Because function descriptions cross page boundaries, be sure
to keep reading until you hit the Source: line.
Begging for money
Yes, after almost five years of distributing GemFast with no
strings attached, I've suddenly become mercenary. It has
something to do with being unemployed at the moment.
If you like GemFast, and you feel generous, please send a
contribution of $15 to the name and address listed under
Support, below. Please do not send currency in the mail, it
encourages crime. If you are outside of the U.S.A., please
don't feel obligated to send a contribution; it's more
trouble than it's worth for you folks to get a check payable
in US funds.
Despite my begging for contributions, GemFast is not
shareware, it is public domain. Here's the deal...
- GemFast v1.9 is 100% Public Domain. I hereby explicitly
release all rights to GemFast v1.9; you can use and
distribute the source and binary in any way you like.
- Programs developed with GemFast can be copyrighted by
you or another party as you see fit; my release of
rights to GemFast is not to be construed as a release of
rights for any work which contains GemFast functions.
- Please keep the distribution archives completely intact
when copying GemFast to other BBS systems. If you've
used GemFast as the GEM support for a compiler, you can
package the files with your compiler as you wish. (IE,
if you're just copying the standard distribution, please
do it my way. If you've repackaged as part of a larger
======================================================================
GemFast v1.8 Page 2
work under another name, do it however you want.)
Support
I love to hear from you, but I don't promise personalized
replies. I do take seriously all input I get on GemFast.
The files AES_VRSN.DOC and VDI_VRSN.DOC contain cumulative
revision notes. If you had only reported it, *your*
favorite bug or enhancement might have been listed there.
Please don't hesitate to send me bug reports, suggestions
for enhancements, or code you've written. Look through your
existing programs...if there are functions that show up in a
lot of them, chances are they'd be at home in the GemFast
libraries, so send them along. A $15 contribution won't be
refused either.
I can be reached on the BIX online system, as "ianl". Via
internet, I can be reached at ianl@bix.com. Questions that
you think might be of general interest can be posted on
usenet in comp.sys.atari.st.tech. (This is the only usenet
newsgroup I read; don't post in the other atari newsgroups
if you expect me to reply.) You can also reach me by snail-
mail, at:
Ian Lepore
6762 Marshall St.
Arvada, CO 80003-4030
USA
I probably won't reply by snail-mail, because my printer is
broken (and there's not a chance of my writing a letter
longhand). If you reach me electronically, I'll generally
reply within a few days.
- Ian Lepore
05/05/93
ianl@bix.com (preferred email address)
ilepore@nyx.cs.du.edu (use this if bix.com fails)
Moderator, BIX atari.st and c.language conferences
Independent Software Developer (read: unemployed)
======================================================================
GemFast v1.8 Page 3
Function Quick-Reference
If you're like me, half the times you look at a library doc
it's because you've forgotten what order the parms are in
for some function. Here's a list of prototypes for all
functions. Full descriptions of each function can be found
in later chapters.
void apl_cleanup(short cleanup_type);
void apl_mmvectors(void *allocfunc, void *freefunc);
void apl_vclose(short vhandle);
short apl_vopen(void);
short apl_vshared(void);
void apl_xexit(void);
short apl_xinit(void);
char *exterror(short errcode);
short exterrset(_Err_tab *msgtab, short install_or_remove);
void frm_confine(OBJECT *tree, GRECT *boundrect);
long frm_defaults(long options);
void frm_desktop(long options, OBJECT *tree);
short frm_dialog(long options, OBJECT *tree, short editobj);
short frm_dsdialog(long options, char **btnarray, char **strarray);
short frm_dsmenu(long options, char *title, char **itemarray);
short frm_eflag(OBJECT *tree, short object, char *fmt, ...);
void frm_enableblit(void);
short frm_error(short errcode, char *buttons, char *fmt, ...);
short frm_menu(long options, OBJECT *tree, short select_state);
short frm_mkmoveable(OBJECT *tree, short mover_object);
short frm_nldialog(long options, char *buttons, char *lines);
short frm_nlmenu(long options, char *title, char *items);
short frm_printf(long options, char *buttons, char *fmt, ...);
short frm_progress(long options, short increments, char *abortbutton,
char *fmt, ...);
short frm_qchoice(char *buttons, char *fmt, ...);
short frm_qerror(short error, char *fmt, ...);
short frm_qmenu(char *title, char *selections);
void frm_qtext(char *fmt, ...);
short frm_question(char *fmt, ...);
void frm_sizes(OBJECT *tree, GRECT *outrect);
short frm_verror(short errcode, char *buttons, char *fmt,
va_list args);
short frm_vprintf(long options, char *buttons, char *fmt,
va_list args);
short fsl_dialog(short options, char *opath, char *ipath,
char *forcewild, char *prompt);
long grf_blit(short options, void *buffer, void *rect_or_tree);
void *grf_memblit(short options, void *buffer, void *rect_or_tree);
short grf_mouse(short newshape, void *usershape);
short mnu_bar(OBJECT *tree, short install_or_remove, long reserved);
void mnu_disable(void);
void mnu_enable(void);
void mnu_erase(void);
void mnu_tbar(char *title_string);
======================================================================
GemFast v1.8 Page 4
short obj_bmbuttons(OBJECT *tree, short parent, short select_state,
short bitmap);
short obj_clcalc(OBJECT *tree, short object, GRECT *grectout,
VRECT *vrectout);
void obj_flchange(OBJECT *tree, short object, short newstate,
int redraw, ...);
void obj_offxywh(OBJECT *tree, short object, GRECT *outrect);
short obj_parent(OBJECT *tree, short object);
char **obj_ppstring(OBJECT *pobj);
short obj_rbfind(OBJECT *tree, short parent, short select_state);
short obj_rbselect(OBJECT *tree, short object, short select_state);
void obj_stchange(OBJECT *tree, short object, short new_state,
int redraw, ...);
short obj_xtfind(OBJECT *tree, short parent, short select_state);
void obj_xywh(OBJECT *tree, short object, GRECT *outrect);
void rc_confine(GRECT *boundrect, GRECT *therect);
void rc_copy(GRECT *source, GRECT *dest);
int rc_equal(GRECT *rect1, GRECT *rect1);
GRECT *rc_gadjust(GRECT *dest, short hadjust, short vadjust);
VRECT *rc_gtov(GRECT *source, VRECT *dest);
int rc_intersect(GRECT *source, GRECT *dest);
short rc_ptinrect(GRECT *therect, short x, short y);
GRECT *rc_scale(GRECT *source, GRECT *dest, short percentage);
void rc_union(GRECT *source, GRECT *dest);
VRECT *rc_vadjust(VRECT *dest, short hadjust, short vadjust);
GRECT *rc_vtog(VRECT *source, GRECT *dest);
short rsc_cubuttons(OBJECT *tree);
void rsc_gstrings(OBJECT *tree, int object, char **ppstring, ...);
void rsc_gtrees(int object, OBJECT **pptree, ...);
short rsc_rrbuttons(OBJECT *tree);
void rsc_sstrings(OBJECT *tree, int object, char *string, ...);
void rsc_sxtypes(OBJECT *tree, int object, int xtype, ...);
void rsc_treefix(OBJECT *tree);
short wnd_top(void);
short wnd_update(short semaphore);
void xob_nslide_change(OBJECT *tree, short object, long newmin,
long newmax)
short xob_nslide_create(OBJECT *tree, short object, long min,
long max)
long xob_nslide_get(OBJECT *tree, short object)
void xob_nslide_set(OBJECT *tree, short object, long newvalue)
short xob_thermo_change(OBJECT *tree, short object,
short increments);
short xob_thermo_create(OBJECT *tree, short object,
short increments);
short xob_thermo_update(OBJECT *tree, short object,
short newpos, GRECT *cliprect);
void xob_transform(XUSERBLK *xub, OBJECT *pobject, void *drawfunc);
short evnx_multi(XMULTI *xm);
short frmx_center(OBJECT *tree, GRECT *outrect);
short frmx_dial(short flag, GRECT *little, GRECT *big);
short grfx_dragbox(GRECT *start, GRECT *boundary, GRECT *end);
short winx_calc(short type, short kind, GRECT inrect, GRECT
======================================================================
GemFast v1.8 Page 5
*outrect);
short winx_get(short whandle, short field, GRECT *outrect);
======================================================================
GemFast v1.8 Page 6
Global Variables
GemFast provides several global variables containing
information about the state of the system and your
application. The GEMFAST.H header file declares all these
variables; you can just refer to them as needed in your
programs. When using compilers other than HSC or GNU C, the
names below are still valid; macros in GEMFAST.H alias the
names below to the actual names used by the compiler's low-
level bindings. A summary of the variables appears below,
followed by detailed information about them.
The following variables are defined by GEM:
short global[]; also aliased by following names...
short gl_apversion; the AES version number
short gl_apcount; max # of concurrent AES applications
short gl_apid; id of the current application
long gl_apprivate; anything application wants to store
void *gl_apptree; pointer to array of object tree ptrs
long gl_ap1resv; old name for pointer to rsc data
RSHDR *gl_aprshdr; pointer to head of rsc data
short gl_ap2resv[6]; unused entries in global array
The following variables are defined by GemFast:
short gl_grfhandle; physical VDI workstation handle
GRECT gl_rwdesk; coordinates of the desktop workarea
GRECT gl_rfscrn; coordinates of the full screen
short gl_hchar; height of a character
short gl_h2char; height of a character divided by 2
short gl_h4char; height of a character divided by 4
short gl_h8char; height of a character divided by 8
short gl_wchar; width of a character
short gl_w2char; width of a character divided by 2
short gl_w4char; width of a character divided by 4
short gl_w8char; width of a character divided by 8
short gl_wbox; width of a boxchar
short gl_hbox; height of a boxchar
The following variables are valid only after one or more
calls have been made to apl_vopen() or apl_vshared():
short gl_vwout[57]; the work_out from v_opnvwk()
short gl_vxout[57]; the work_out from vq_extnd(,1,)
The GEM-defined variables are documented in any manual or
textbook on GEM programming. The gl_ names in this group
are just aliases for the items in the global array. (That
is, gl_apversion is just another name for global[0], etc.)
The GemFast-defined variables contain data that many GemFast
library routines (and GEM programs in general) need frequent
======================================================================
GemFast v1.8 Page 7
access to. You can refer to these values in your code any
time after you've called appl_init(). The values in these
variables will never change, and you must never change them;
they are for reference only.
The gl_grfhandle variable contains the physical VDI
workstation handle owned by the AES. This is the value
returned by graf_handle(). You should never use this handle
directly in your VDI calls; the only proper use is to pass
this value to VDI when opening a virtual screen workstation.
The gl_wchar, gl_hchar, gl_wbox, and gl_hbox variables
contain the sizes of a character and a box that will hold a
character. These are the values returned by graf_handle().
They are very useful values, please use them whenever you
can instead of hard-coding size constants (which may be
wrong when alternate monitors are in use). The variables in
this group that have 2, 4, and 8 in the name are useful for
creating resolution-independent fine alignments when you
dynamically construct or modify objects at runtime.
The gl_rwdesk structure contains the xywh values that
describe the work area of the desktop (everything on the
screen except the menu bar area, generally). The gl_rfscrn
structure contains the xywh values that describe the full
screen. These values can be handy for clipping and
confining operations; just pass their address (don't forget
the '&' character!) to the rectangle calculation functions
as needed.
The gl_vwout array contains the values that v_opnvwk() puts
into the work_out array. The gl_vxout array contains the
values from vq_extnd(handle, 1, gl_vxout). The values in
these two arrays are valid only after you've opened a VDI
workstation by calling apl_vopen(). These arrays are
defined in a different module than the other global
variables, and will only be linked into your program if you
actually use VDI (or use a GemFast function which uses VDI).
Some of the variables are defined and initialized by GEM
during the appl_init() call, and others are defined and
initialized by GemFast during the apl_xinit() call. A macro
in GEMFAST.H remaps your existing appl_init() calls through
the new apl_xinit(). Do NOT undo this mapping macro! The
GemFast library routines count on the data in the global
variables being accurate, and that will only happen if
control was passed through apl_xinit() on the way to the
real GEM init function.
In general, I don't like global variables in C programs very
much. But, as the GemFast library routines became more
complex, I found that every new routine was calling GEM to
get the height of a character or the rectangle describing
the system desktop or something. It was getting to be a
======================================================================
GemFast v1.8 Page 8
real performance problem. So, I looked back through five
years worth of programs I've written, and decided on a small
set of global variables to hold the information that most
GEM programs seem to need. Note that all of these variables
are items that you should consider as being read-only in
nature. (Somehow I feel that helps justify their existence
as global variables.)
======================================================================
GemFast v1.8 Page 9
Application Library
Application library routines provide an interface between
your program and the host environments that can supply
services and resources to you. Those hosts include GemFast
itself, the GEM VDI and AES, and GEMDOS. In general,
application library routines help you manage system
resources.
======================================================================
GemFast v1.8 Page 10
void apl_cleanup(short options)
______________________________________________________________________
Summary: Cleanup resources acquired internally by other library
routines.
Input: The options parameter specifies the type of resources to
clean up. OR together any of the following:
APL_RTRANSIENT - Temporary resources, such as the shared
VDI workstation.
APL_RPERMANENT - Permanent resources, such as attachments
to RSC data.
Returns: Nothing.
See also: apl_xexit()
Details: Some library routines acquire system resources (VDI handle,
blocks of memory, etc) in the course of processing. This
function releases those resources.
This is intended primarily for desk accessories. When an
AC_CLOSE message is received, call this function with a
flag value of APL_RTRANSIENT. If the desk accessory is
going to unload itself, or has detected that a resolution
change is happening, call this function with a flag value of
(APL_RTRANSIENT | APL_RPERMANENT).
For a non-accessory program, a cleanup happens automatically
when you call appl_exit(); you don't need to call
apl_cleanup() explicitly.
Right now, the only transient resource is the shared VDI
workstation, and there are no permanent resources. That
will change soon.
Source: aesfuncs\aplxinit.c
======================================================================
GemFast v1.8 Page 11
void apl_mmvectors(void *allocfunc, void *freefunc)
______________________________________________________________________
Summary: Specify the memory management routines for GemFast library
functions to use when they need to allocate memory.
Input: The allocfunc parameter is a pointer to a memory allocation
routine.
The freefunc parameter is a pointer to the memory free
routine associated with the allocfunc allocation routine.
Returns: Nothing.
See also:
Details: Some GemFast library routines need to allocate and free
blocks of memory. By default, your compiler's runtime
library allocation functions (malloc, lalloc, free) will be
used.
The most common use of this function will be to supply your
own memory allocation functions, for debugging or better
performance or whatever. The allocation function must
accept a longword parameter and return a 32-bit pointer.
Often this function is called lalloc() or farmalloc() in
your compiler library. So the most common use would look
like this:
apl_mmvectors(lalloc, free);
If you want to write your own memory management functions,
here are some rules... The allocator has to accept a
longword size parameter, and return a 32-bit pointer. It
returns NULL if the memory can't be allocated. The free
function has to accept a 32-bit pointer; it returns nothing.
Do NOT write an 'intercept' allocator that accepts a
longword size and passes it along to malloc() as a 16-bit
value. A huge moveable dialog box could occupy more than
64k of screen memory on a high-resolution system.
Source: aesfuncs\aplmallo.c
======================================================================
GemFast v1.8 Page 12
void apl_vclose(short vdi_handle)
______________________________________________________________________
Summary: Close a VDI workstation opened with apl_vopen().
Input: The vdi_handle parameter is a handle to a VDI virtual screen
workstation.
Returns: Nothing.
See Also: apl_vopen() apl_cleanup()
Details: This function closes a VDI workstation that was opened with
a call to apl_vopen(). It will not close the shared
workstation; only apl_cleanup() can close the shared
workstation.
Source: aesfuncs\aplvwork.c
======================================================================
GemFast v1.8 Page 13
short apl_vopen(void)
______________________________________________________________________
Summary: Open a VDI virtual screen workstation.
Input: Nothing.
Returns: A VDI handle, or 0 if no handles are available.
See Also: apl_vclose()
Details: This function provides a simple way to open a VDI screen
workstation. It automatically handles the work_in and
work_out arrays, and other basic details for you.
The values from the work_out array are available in the
global array gl_vwout any time after a VDI workstation
(including the shared workstation) is opened. The values
returned by vq_extnd(,1) are also available in gl_vxout.
The work_in array is built automatically to set up the
following default configuration:
static short work_in[11] = {
-1, /* device driver (filled in at runtime) */
1, /* polyline type (normal) */
1, /* polyline color (black) */
1, /* polymarker type (dot) */
1, /* polymarker color (black) */
1, /* text face (standard) */
1, /* text color (black) */
1, /* fill interior (solid) */
8, /* fill style (solid) */
1, /* fill color (black) */
2 /* use RC coordinate system */
};
After the workstation is open, you can change its attributes
as you wish, using the vs_whatever() VDI functions.
Source: aesfuncs\aplvwork.c
======================================================================
GemFast v1.8 Page 14
short apl_vshared(void)
______________________________________________________________________
Summary: Returns the handle for the shared VDI workstation, opening
the shared workstation if necessary.
Input: Nothing.
Returns: The handle of the shared VDI virtual screen workstation, or
0 if no workstation is available.
See Also: apl_vopen() apl_cleanup()
Details: This function opens the shared VDI workstation if it isn't
open already, and returns the handle for it.
GemFast library routines need a lot VDI-based services,
especially for blitting and custom object drawing. Instead
of having each routine open and close VDI workstations as
needed, all routines now use the shared workstation. Once
the shared workstation is opened, it remains open from that
point on. (Unless you call apl_cleanup() to close it.) If
opened during the run of a program, appl_exit() closes it.
Your application can use the shared workstation for
blitting, but I strongly recommend against using it for
other VDI operations. Any given library function could want
the shared workstation, and it expects the attributes to be
set to a standard configuration. It would be difficult for
you determine whether it's "safe" to change the attributes
at any given point to do some sort of output and then set
them back. The shared workstation can even get used by the
AES itself, because some library routines install custom
G_USERDEF drawing routines that get called by the AES
automatically.
Source: aesfuncs\aplvwork.c
======================================================================
GemFast v1.8 Page 15
void apl_xexit(void)
void appl_exit(void)
______________________________________________________________________
Summary: Cleanup acquired system resources, inform the AES that the
program is about to exit.
NOTE: A macro in GEMFAST.H remaps appl_exit to apl_xexit, so that
the extended exit function is automatically used when you
recompile your existing code.
Input: Nothing.
Returns: Nothing.
See Also: apl_xinit() apl_cleanup()
Details: Currently, apl_xexit() just calls apl_cleanup() to release
permanent and transient resources, then it calls the real
appl_exit() function for you. The primary purpose for the
extended exit function right now is to ensure that the
shared VDI workstation gets closed. In the future, it'll do
more.
Source: aesfuncs\aplxinit.c
======================================================================
GemFast v1.8 Page 16
short apl_xinit(void)
short appl_init(void)
______________________________________________________________________
Summary: Register your application with the AES, and load values into
the GemFast-defined global variables.
NOTE: A macro in GEMFAST.H remaps appl_exit to apl_xexit, so that
the extended init function is automatically used when you
recompile your existing code.
Input: Nothing.
Returns: Application ID return by the AES, or a negative number if
the AES is not available.
See Also: apl_xexit()
Details: The extended init first calls the real appl_init() function.
If that succeeds, it calls several inquiry functions to load
the global variables with data that most GEM programs need,
such as the sizes of the system desktop. The chapter Global
Variables contains complete details on the global variables
initialized by this function.
Source: aesfuncs\aplxinit.c
======================================================================
GemFast v1.8 Page 17
Error Message Library
The error message library contains several functions which
help support error reporting functions in the forms library.
They are not, strictly speaking, GEM functions. You may
find them useful even in your non-GEM programs.
The functions allow you to specify tables of error messages
and their associated error codes. You can then report an
error message just by passing the code to frm_[q]error().
TOS reserves error codes in the range of -1 to -128. Code 0
is, by convention, success. Many compilers reserve a range
of codes for runtime library errors (HSC reserves -129
through -255 for this); consult your compiler documentation
for details. Some compilers reserve a range of positive
rather than negative numbers.
GemFast reserves codes in the range of -15100 through -15199
for reporting GemFast internal errors. This seems like a
small range in the middle of nowhere, and shouldn't conflict
with existing code.
======================================================================
GemFast v1.8 Page 18
char * exterror(short errcode)
______________________________________________________________________
Summary: Return a text description of the specified error code.
Input: The errcode parameter is the numeric error code you want the
text description of.
Returns: A pointer to a \0-terminated string describing the error.
Do not modify the string this points to. The return value
is guaranteed to be non-NULL, but it may point to an empty
string ("").
NOTE: You must code a #include "exterror.h" to use this function.
See Also: exterrset()
strerror() (in your compiler's library)
Details: This function is similar to the strerror() function defined
by ANSI, except that it first searches tables of
application-specific error messages (installed by the
application using exterrset()). If the application-specific
tables don't contain a message for the specified error
number, this function calls the standard strerror() function
to obtain the system-defined message.
This function can also deal with positive error codes, both
in the extended message tables and for strerror() if your
compiler's errno system uses positive error codes.
Source: aesfuncs\exterror.c
======================================================================
GemFast v1.8 Page 19
short exterrset(_Err_tab *ptab, short install_or_remove)
______________________________________________________________________
Summary: Installs or removes a table of application-specific error
codes and their associated messages.
Input: The ptab parameter is a pointer to an array of _Err_tab
structures coded in your application.
The install_or_remove parameter is a flag indicating whether
the specified table is to be installed in the list of
extended message tables, or removed from that list. A table
can be safely removed more than once.
Returns: 0 on success, or -1 if there are no more slots available in
the extended tables list.
NOTE: You must code a #include "exterror.h" to use this function.
See Also: exterror()
Details: This function installs or removes tables of application-
specific error messages. The exterror() function returns
message from these tables. You create extended message
tables by coding an array of _Err_tab structures and
initializing the array with your codes and messages. The
_Err_tab structure is defined in EXTERROR.H, as follows:
typedef struct _Err_tab {
int code;
char *msg;
} _Err_tab;
To create a table of extended messages, code an array and
initialize it with your errcode/msg pairs. Use an error
code value of zero to indicate the end of the table. You
can define any error code in the range of -32768 through
32767, excluding code 0. If you provide messages for
system-defined error codes, exterror() finds your messages
first, and returns them instead of calling strerror(). In
other words, you can override the wording of system
messages.
Example: The following is an example of creating and installing an
extended error message table defining 3 application-specific
messages:
static _Err_tab my_messages[] = {
{-300, "Input must be between 0 and 200"},
{-301, "Cannot locate configuration file"},
{-302, "Internal data corrupted"},
{0, NULL};
exterrset(my_messages, TRUE);
======================================================================
GemFast v1.8 Page 20
Note that I don't check the return code from exterrset() in
the example. You really should check it. ::grin::
The internal list is currently configured for up to 8
extended message tables.
Source: aesfuncs\exterror.c
======================================================================
GemFast v1.8 Page 21
Forms and Dialogs Library
The forms and dialogs library contains functions related to
dialog processing. Some of the functions are designed to
help you conduct your own dialogs, and others invoke pre-
written dialogs using your parameters and messages.
The pre-written dialogs use options and strings you specify,
and dynamically build and conduct a dialog based on them.
For this reason, they are collectively referred to as the
'dynamic' dialogs. The dynamic dialogs are divided into two
groups, the basic functions and the quick functions. The
basic functions allow you to specify options and a variety
of exit buttons. The quick functions are easy to call; they
provide default options and buttons. (The quick functions
do not execute faster; they're quicker to code.) The basic
dynamic dialogs exist primarily to support the higher-level
quick dialogs, but there's no reason you can't use them
directly if you need the extra options or buttons.
Summary of Dialog Functions
The functions which help you conduct your own dialogs are:
frm_confine Confines dialog to rectangular area.
frm_defaults Sets default options.
frm_dialog Conducts your standard dialog.
frm_menu Conducts your menu (object tree) dialog.
frm_enableblit Enables screen save/restore via blit.
frm_eflag Reports error made by user in a dialog.
frm_mkmoveable Makes your dialog moveable.
frm_desktop Installs your custom desktop.
frm_sizes Calculates dialog's on-screen sizes.
The basic dynamic dialogs are:
frm_dsdialog Automatic text dialog - hard to use.
frm_nldialog Automatic text dialog - easier to use.
frm_dsmenu Automatic menu dialog - hard to use.
frm_nlmenu Automatic menu dialog - easier to use.
frm_printf Formatted text dialog, like printf().
frm_progress Formatted progress display.
frm_error Formatted error reporting.
frm_verror Alternate form of frm_error.
frm_vprintf Alternate form of frm_printf.
frm_vprogress Alternate form of frm_progress.
======================================================================
GemFast v1.8 Page 22
The quick dynamic dialogs are:
frm_qchoice Formatted text and choice of 5 buttons.
frm_qerror Formatted error msg - 'Continue' button.
frm_qfatal Formatted error msg - 'Fatal' button.
frm_qmenu Automatic menu (like dropdown in a box).
frm_qtext Formatted text display.
frm_question Formatted yes/no question.
If you look in the GemFast source code, you may find some
other functions in the frm_ family. Do NOT use any
functions not described in this document. If it's not
documented here, I guarantee you the calling standard for it
will change in the next version, and your programs will
break. If it wasn't in a state of flux, it'd be documented.
Dialog Processing Options
At the root of all dialog processing in GemFast is the
frm_dialog() function. All dynamic dialogs eventually end
up in it, including the menu dialogs. You can also use it
for processing your custom application dialogs. There are a
variety of options that frm_dialog() can act on for you.
Several of the dynamic dialogs have options that apply
specifically to them, but not to dialog processing in
general. All dialog processing options are listed below.
In addition to options which control the appearance of a
dialog, some functions accept action flags which dictate the
steps or parts of a dialog to be performed. This applies
primarily to the frm_dialog() function. Because they are
specific to only a few of the functions, action flags are
described along with the function that uses them.
It makes sense for all dialogs in an application to behave
pretty much the same way, so GemFast provides the
frm_defaults() function to specify default dialog options.
You can set the default options once, during program
startup, then use just FRM_NORMAL in all your dialog
function calls, and everything (including dynamic dialogs
which don't let you specify any options) will behave
according to the defaults you set.
The options parameter for all dialog library functions is a
longword. It is important for you to use the constant
FRM_NORMAL instead of just 0 or NORMAL when you want no
special options. Options are encoded in the longword as a
======================================================================
GemFast v1.8 Page 23
collection of bits. The bits for different types of options
appear in distinct places in the longword (not that this
really has much affect on you in the current version) as
follows:
0xAUDDBBBB
||| |______ Basic options for all dialog handling.
|||________ Dynamic dialog options.
||_________ User options; never touched by GemFast.
|__________ Actions.
Basic Dialog Options
The FRM_NORMAL option is really a placeholder that says you
want no options other than the defaults already established.
The FRM_EXPLODE option draws exploding-box graphics during
the start and finish phases of a dialog. The small box for
the grow/shrink calls is one-fifth the size of the full
dialog, centered under the full dialog.
The FRM_MOUSEARROW option forces the mouse cursor shape to
an arrow for the duration of the dialog, then changes it
back to the prior shape when the user exits.
The FRM_CENTER option centers the dialog within the desktop
before drawing it.
The FRM_NEARMOUSE option centers the dialog over the current
mouse location (adjusting as necessary to keep the dialog
wholly on-screen) before drawing it. FRM_NEARMOUSE takes
precedence over FRM_CENTER when both are specified.
The FRM_USEBLIT option saves and restores the screen under
the dialog using blits instead of redraw messages. You must
call frm_enableblit() at least once before this option is
honored. This option only has effect when the frm_dialog()
action flags are equal to FRM_DCOMPLETE (ie, when you're
doing all phases of the dialog in a single call). The blit
buffer is allocated and freed by frm_dialog(). If the
allocation fails, the FRM_USEBLIT option is turned off for
the duration of that frm_dialog() call.
The FRM_MOVEABLE option designates the dialog as moveable
even if no object in the dialog has the FRM_MOVER bit on in
its ob_flags. The FRM_USEBLIT option has to be in effect
for this option to function, and all conditions required for
FRM_USEBLIT to take effect apply to this option as well. If
you have used frm_mkmoveable() to designate a specific mover
object within a dialog, this option has no effect; the mover
object will always move the dialog regardless of this
option. If you specify this option for a dialog that has no
======================================================================
GemFast v1.8 Page 24
designated mover object, the root object becomes the dialog
mover automatically. The basic point to this option is that
you can set it as the default, and all your dialogs suddenly
become moveable even when you haven't designed in a mover
object. If allocation of a blit buffer fails, the dialog is
treated as unmovable. When your dialogs stop moving, you're
getting low on memory.
The FRM_NODEFAULTS option can be passed to frm_dialog() or
the dynamic dialogs to disable the default options for that
specific call. When you pass FRM_NODEFAULTS as one of your
options, the default options are ignored, and only the
options passed along with FRM_NODEFAULTS are used.
Dynamic Dialog Options
The FRM_DSHADOWED option draws the parent box of the dynamic
dialog (text or menu) as a SHADOWED object instead of an
OUTLINED object.
The FRM_DMUSTSELECT option is interpreted based on the type
of dialog. For a text dialog, it indicates that there is no
default exit button; the user "must select" a button with
the mouse. For a menu dialog, it indicates that the user
must click on a selectable item; clicking outside the dialog
box does not end the dialog and return NO_OBJECT.
The FRM_DEFAULTLEFT option causes the default button in
dynamic dialogs to be the leftmost (rather than rightmost)
button. For the frm_question() dialog, it also causes the
left button to be 'Yes' and the right button to be 'No'.
The FRM_MEXITPARENT option causes the menu dialog to return
NO_OBJECT as soon as the mouse leaves the dialog box. This
option applies only to menu dialogs and has no effect on
text dialogs.
The FRM_MEXITVICINITY option cause the menu dialog to return
NO_OBJECT as soon as the mouse leaves the near vicinity of
the dialog box. The vicinity is an area that extends four
character widths to either side of the dialog box and two
characters heights above and below it. This option applies
only to menu dialogs and has no effect on text dialogs.
The MUSTSELECT option takes precedence over MEXITPARENT and
MEXITVICINITY. When MUSTSELECT is specified, you are
guaranteed never to get a NO_OBJECT return value.
======================================================================
GemFast v1.8 Page 25
Dynamic Dialog Defaults
For dynamic dialogs that allow you to specify a list of exit
buttons, a NULL button pointer gives you a single exit
button containing "Continue" as its text. You also get a
Continue button for the quick dynamic dialogs that don't let
you specify a list of buttons.
While it's pretty pointless to do so, if you pass a NULL
pointer for the text string or format string describing the
body of the dialog, the body will be a single line
containing "<no message>".
All dynamic dialogs use a default internal options list.
These automatic defaults are added to the options you set
with frm_defaults() and whatever you specify in the call.
The automatic dynamic dialog defaults are:
(FRM_CENTER | FRM_USEBLIT | FRM_MOVEABLE | FRM_MOUSEARROW)
As usual, if you specify NEARMOUSE it takes precedence over
the default CENTER. The USEBLIT and MOVEABLE defaults are
honored only if you've called frm_enableblit(). If you pass
FRM_NODEFAULTS to a dynamic dialog, the defaults listed
above are not used, only the options you specify in that
call are used. An oddball exception is that if you specify
NODEFAULTS and don't include CENTER or NEARMOUSE, CENTER is
assumed (otherwise where would the dialog be placed?).
Text and Button Formatting in Dynamic Dialogs
A number of common factors apply to all dynamic dialog
functions that handle formatted text and/or multiple
buttons. These details apply to any function which lists
frm_printf() in its See Also: section.
Dynamic dialogs construct a dialog box around your text
and/or button. The dialog box is automatically sized to
contain the widest line of text in the body, or wide enough
to hold all the buttons, whichever is greater. It is YOUR
responsibility to ensure that the strings don't result in a
width greater than the current screen width.
Dynamic text dialogs can display up to 20 lines of formatted
text, with a total of no more than 2k for the entire
message. The 2k limit is more than enough to format 20
lines of 80 characters, and should thus not be a problem.
The GEMFAST.H file defines a constant, FRM_DSMAXLINES if you
should need to refer to the line limit in your code.
Any line of text in the message which has a 0x7F character
======================================================================
GemFast v1.8 Page 26
in the first position is automatically centered horizontally
(the 0x7F is not displayed). A 0x7F character in any other
position displays as normal (a little triangle thingy on my
system).
Dynamic dialogs which allow you to specify multiple buttons
can display a maximum of 5 buttons. The lengths of all the
button text strings should not exceed about 70 characters,
or the dialog will end up being wider than the typical 80-
character screen width. All buttons are formatted to the
same width, that required to hold the longest button string.
The buttons are distributed uniformly across the bottom of
the dialog box. The GEMFAST.H file defines a constant,
FRM_DSMAXBUTTONS if you should need to refer to the button
limit in your code..
The button selected by the user is the return value from the
dynamic dialog function. The leftmost button is 0, and the
number increments as you proceed right.
If any button has a 0x7F character in the first character,
that button is made the default exit button, regardless of
the FRM_DMUSTSELECT or FRM_DEFAULTLEFT options. (Don't put
a 0x7F on more than one button!) If no buttons are
explicitly marked as the default with 0x7F, the following
rules apply.
If FRM_DEFAULTLEFT is in effect, the leftmost button is the
default exit button. This conforms to the new Atari
application guidelines released with the Falcon 030
documentation. An increasing number of applications are
going to be using the leftmost button as the default, and
that button will generally be the 'Yes', 'Okay', 'Continue',
or other positive-action selection. The rightmost button
should be Exit, Cancel, No, or the negative-action button.
If FRM_DMUSTSELECT is in effect, none of the buttons are
automatically marked as the default exit button.
Otherwise, the rightmost button is the default exit button.
This is a holdover from long ago, maintained for
compatibility; it does not conform to Atari's current
guidelines. You should set FRM_DEFAULTLEFT in your
frm_defaults() list, and make any necessary changes to your
existing dynamic dialog calls, as soon as possible.
======================================================================
GemFast v1.8 Page 27
void frm_confine(OBJECT *ptree, GRECT *boundrect)
______________________________________________________________________
Summary: Adjust the location of an object tree so that it is confined
within a specified area.
Input: The ptree parameter is a pointer to the tree to adjust.
The boundrect parameter is a pointer to the rectangle in
which the tree is to be placed.
Returns: Nothing.
See also: rc_confine()
Details: This function adjusts the x/y values of the object tree as
needed to keep that tree within the specified rectangle. It
never modifies the width or height of the tree; if the tree
will not wholly fit within the boundary rectangle, it is
aligned to the upper and left sides of the boundary as
needed. This function takes OUTLINED and SHADOWED flags
into account, and makes sure the dialog is entirely within
the boundary, visually.
Source: aesfuncs\frmconfi.c
======================================================================
GemFast v1.8 Page 28
long frm_defaults(long options)
______________________________________________________________________
Summary: Get or set default dialog processing options.
Input: The options parameter specifies the new default options as a
bitmap; the available values are described under Dialog
Processing Options. In addition, the following special
value may be passed instead of the standard options:
FRM_GETDEFAULTS - Return the current defaults without
changing them.
Returns: The default options in effect before the call.
See Also: frm_dialog()
Details: The dialog functions support a variety of processing
options. You can pass options to most of them on each call.
In addition, you can use this function to set default
options that will be used on every subsequent call to
frm_dialog() or a dynamic dialog. The default options set
by this function will apply to any other library function
which lists frm_defaults() in its "See Also" section.
Library routines will NOT change the default options behind
your back. Library routines calling frm_dialog() do NOT use
FRM_NODEFAULTS to override your preferences.
Source: aesfuncs\frmdialo.c
======================================================================
GemFast v1.8 Page 29
void frm_desktop(long options, OBJECT *ptree)
______________________________________________________________________
Summary: Installs or removes an object tree as the system desktop.
Input: The options parameter specifies the installation option, use
one of the following values:
FRM_NORMAL - No options; the tree is installed
without any changes.
FRM_CENTER - The tree is automatically fitted to the
desktop.
The ptree parameter is a pointer to the object tree to
install as the new desktop. When NULL, it indicates you are
removing any custom desktop you've previously installed.
Returns: Nothing.
See Also:
Details: This function makes the specified object tree the new
desktop, for the duration of your program or until you
remove it with another call to this function. Desk
accessories MUST NOT use this function.
The desktop is automatically repainted by the AES; it acts
as if the AES is running an evnt_multi() loop internally,
and responds to redraw messages for the desktop by calling
objc_draw() on the desktop tree. The default system desktop
is a single G_BOX object with no borders or outline.
By installing your own dialog as the system desktop, you can
get the benefits of a windowed program without the hassle of
using window redraw logic in your program. If your
application has a single main dialog box, you can install it
as the desktop and call other dialog functions -- even the
file selector -- and your main dialog is automatically
redrawn as other windows and dialogs are closed or moved.
After installing your tree as the desktop, this function
sends out redraw messages which cause it to be painted
automatically. You never need to call objc_draw() to show
the tree. If the tree is a dialog, just call form_do() (or
frm_dialog(FRM_DDO)) to start the dialog, and don't call
form_dial(FMD_FINISH) when you're done.
To use a dialog as the desktop, I recommend that you create
the main dialog box as a borderless non-outlined box filled
with solid green. Make the second object in the tree a box
with an inside width of 2 and OUTLINED. (IE, the second
object is a box just like the one used as the first object
in a normal dialog.) Then call this function, passing an
option of FRM_CENTER. The FRM_CENTER option causes this
======================================================================
GemFast v1.8 Page 30
function to automatically adjust the main box (the first
object) to be exactly the size of the system desktop, and
then it centers the second object (the actual dialog box)
within the desktop. Visually, you get the effect of a
dialog that has been form_center'd on a regular desktop.
If you don't use the FRM_CENTER option, you MUST ensure that
the first object in the tree is exactly the size of the
desktop.
When your desktop root object has been defined as a box
filled with a solid non-background color (eg, a standard
solid green desktop), this routine modifies the box to a 50%
gray fill when running on a monochrome system. (Otherwise
the "solid green" box would appear as solid black on a
monochrome monitor.) In other words, if you follow the
recommendation of designing a solid green desktop, this
routine automatically adjusts the desktop to match the
standard system desktop when running on monochrome monitors.
Source: aesfuncs\frmdeskt.c
======================================================================
GemFast v1.8 Page 31
short frm_dialog(long options, OBJECT *ptree, short startobj)
______________________________________________________________________
Summary: Conducts all or part of a dialog with the user.
Input: The options parameter specifies actions and options as a
bitmap; the available values are described under Dialog
Processing Options. In addition to the options, any of the
following actions can be ORed into the parameter value:
FRM_DSTART - Do the FMD_START and FMD_GROW.
FRM_DDRAW - Do the objc_draw().
FRM_DDO - Do the form_do().
FRM_DFINISH - Do the FMD_SHRINK and FMD_FINISH.
FRM_DCOMPLETE - Do all of the above in one call.
If no actions are provided, FRM_DCOMPLETE is assumed.
The ptree parameter is a pointer to the dialog tree.
The startobj parameter is interpreted according the action
options. If just FRM_DDRAW is requested, startobj is the
object to start drawing at. If actions other than drawing
are also requested, the full object tree is drawn, and
startobj is the initial text edit object for form_do().
Returns: The index of the exit object. Be aware that if the exit
object was a TOUCHEXIT, and the user double-clicked on it,
the high bit in the return value is set (making it look
negative). If the exit object had the EXIT or DEFAULT bits
on in its ob_flags, it is automatically set to ~SELECTED,
both in the object structure, and visually on the screen.
See Also: frm_enableblit() frm_defaults()
Details: The most frequent use of this function is really fairly
simple. To conduct a complete interaction with a user, you
only need to code something like:
selection = frm_dialog(FRM_CENTER, mydialog, 0);
You can, of course, use any of the other options. You can
also use this function to conduct a dialog "in pieces". (A
disadvantage to this is that a dialog conducted in pieces
won't honor the USEBLIT and MOVEABLE options.) Such a
sequence usually appears something like:
- Start dialog using frm_dialog(FRM_DSTART|FRM_DDRAW).
- Loop:
- Conduct interaction using frm_dialog(FRM_DDO).
- Validate user's actions, if any errors are found,
use frm_eflag() to report them.
- When the validations are good, exit the loop.
- Close dialog using frm_dialog(FRM_DFINISH).
======================================================================
GemFast v1.8 Page 32
When you're processing a dialog in pieces, it can be
important to know which options are processed during which
pieces of the dialog. Processing occurs in several phases:
setup - 1. Call wnd_update(BEG_UPDATE).
2. If FRM_USEBLIT is set, ensure that
frm_enableblit() has been called and
that FRM_DCOMPLETE was specified.
Ensure that a blit buffer is available.
If any of those are false, turn off
FRM_USEBLIT.
3. If the dialog contains an object flagged
as the FRM_MOVER object, set
FRM_MOVEABLE on.
4. If FRM_MOVEABLE has been set, ensure
that FRM_USEBLIT is in effect. If there
isn't an FRM_MOVER object, make the root
object the mover.
FRM_DSTART - 1. Center the dialog on the desktop if
FRM_CENTER is set, or center it over the
mouse if FRM_NEARMOUSE is set.
2. Save the screen to the blit buffer if
FRM_USEBLIT is set. Do the FMD_START,
and if FRM_EXPLODE is set do the
FMD_GROW.
FRM_DDRAW - Do the objc_draw().
FRM_DDO - 1. Change the mouse to an arrow if
FRM_MOUSEARROW is set.
2. Do the form_do(). If the exit object
was the FRM_MOVER object, handle the
dialog move, then loop back into
form_do() again.
3. Reset the ob_state of the exit object to
~SELECTED, if it's an EXIT or DEFAULT
object.
4. Restore the mouse shape.
FRM_DFINISH - 1. Do the FMD_SHRINK if FRM_EXPLODE is set.
2. If FRM_USEBLIT is set, blit back the old
screen contents, else do the FMD_FINISH
to send out redraw messages.
cleanup - 1. Free the blit buffer (if any).
2. Call wnd_update(END_UPDATE).
The setup and cleanup phases are done on every call. The
other phases are done when the corresponding action bit is
on in the options.
This function is fail-proof; if a blit buffer can't be
======================================================================
GemFast v1.8 Page 33
obtained, the dialog becomes unmovable, and redraw messages
are sent out after the dialog to restore the screen.
Source: aesfuncs\frmdialo.c
======================================================================
GemFast v1.8 Page 34
short frm_dsdial(char **strings, char **buttons, short explodeflag)
short frm_dsdialog(long options, char **buttons, char **strings)
______________________________________________________________________
Summary: Dynamic string dialog. Builds and conducts a dialog using
the specified strings and buttons.
NOTE: The frm_dsdial() format is outdated; use frm_dsdialog().
Input: The options parameter contains a bitmap of options as
described under Dialog Processing Options.
The buttons parameter is a pointer to an array of string
pointers. Each element in the array is a pointer to the
string to display in one of the buttons. You can display up
to 5 buttons. The end of the array is marked by a NULL
string pointer. If the buttons parameter is NULL, a single
button labeled "Continue" is displayed. The buttons are
displayed left-to-right in the same order as they are in
the array.
The strings parameter is a pointer to an array string
pointers. Each element in the array is a pointer to a
string displayed within the body of the dialog. You can
display up to 20 lines of text. The end of the array is
marked by a NULL string pointer. If the strings parameter
is NULL, a line containing "<no message>" is displayed in
the body of the dialog.
Returns: The index of the button the user clicked on to exit the
dialog, guaranteed to be in the range of 0 through 4. The
leftmost button is 0.
See Also: frm_printf() frm_defaults() frm_nldialog() frm_qtext()
Details: This is a fairly hostile function, so let me start by
recommending that you consider using frm_printf() or
frm_qtext() instead of calling this directly.
This function builds a dialog from the text and buttons you
specify, and conducts the dialog with the user.
======================================================================
GemFast v1.8 Page 35
Example: You must create arrays to hold pointers to the button
strings and lines of text in the body. The following
example displays a dialog with 3 buttons and several lines
of text:
char *buttons[] = {
"Cancel", /* button 0 */
"Ignore", /* button 1 */
"Retry", /* button 2 (default) */
NULL /* mark end of array */
};
char *text[] = {
"\x7F" "Error!", /* center this line */
"Could not open configuration file.",
" ",
"Please select one of the following options:",
NULL /* mark end of array */
};
option = frm_dsdialog(FRM_DSL1TITLE, buttons, text);
Source: aesfuncs\frmdsdia.c
======================================================================
GemFast v1.8 Page 36
short frm_eflag(OBJECT *ptree, short object, char *fmt, ...)
______________________________________________________________________
Summary: Visually flag a dialog object and display an error message.
Input: The ptree parameter is a pointer to the dialog tree.
The object parameter is the index of the object to be
flagged.
The fmt parameter is a printf-style format string containing
the error message.
The ... parameters are values to substitute into the format
string.
Returns: Zero on success or -1 on failure.
See also: frm_printf()
Details: This function reports an error the user made in interacting
with a dialog. For example, if a dialog contains a editable
field which must contain a value, and the user exits the
dialog without filling in that field, this function is an
ideal way to report the error to the user.
This function works with dialogs already visible on the
screen. The object you specify is circled with a red
outline, and a box (a bit like a post-it note) appears
nearby containing the error message text. When the user
hits a key or clicks the mouse button the screen is restored
to its original appearance and this function returns.
Any type of object can be specified as the object to be
flagged. For example, if you have a collection of buttons
and the user must select at least one, specify the parent
box which contains the button group.
The error message can contain up to 20 lines of text. The
longest line must not exceed the screen width. As a
practical matter, it's a good idea to keep the message down
to 5 or 6 lines, each line no more than about one third to
one half the screen width. Any line that starts with 0x7F
is centered in the display box (the 0x7F character is not
displayed).
It is possible for this routine to fail internally, if a VDI
workstation is not available or a blit buffer can't be
allocated. In this case, an alert appears to tell the user
"An error has occurred with a dialog item you selected or
modified, but there are not enough system resources to
report the exact error." If this happens, -1 is returned.
Example: To display a dialog, and ensure that the text edit field is
======================================================================
GemFast v1.8 Page 37
non-blank, the code might look like this:
frm_dialog(FRM_DSTART|FRM_DDRAW, mydialog, 0);
do {
exitobj = frm_dialog(FRM_DDO, mydialog, EDITFIELD);
if (exitobj == OKAY && edit_field_data[0] == '\0') {
frm_eflag(mydialog, EDITFIELD,
"\x7F" "You must supply a value between\n"
"\x7F" " %d and %d for this field",
lower_range, upper_range);
valid_entry = FALSE;
} else {
valid_entry = TRUE;
}
} while (!valid_entry);
frm_dialog(FRM_DFINISH, mydialog, 0);
Source: aesfuncs\frmeflag.c
======================================================================
GemFast v1.8 Page 38
void frm_enableblit(void)
______________________________________________________________________
Summary: Enable the FRM_USEBLIT and FRM_MOVEABLE dialog options.
Input: Nothing.
Returns: Nothing.
See Also: frm_defaults() frm_dialog()
Details: This function sets an internal pointer so that frm_dialog()
can call the grf_blit() function to save and restore the
screen. You only have to call this function once, then from
that point on the FRM_USEBLIT flag is honored during dialog
processing.
Here's the deal... GemFast needed an option to use blitting
instead of redraw messages to save/restore the screen during
dialog processing. But, if frm_dialog() were to contain a
direct call to grf_blit(), your linker would pull in all the
VDI code needed to support blitting, even if you didn't want
the FRM_USEBLIT option active in your program.
So instead of making a direct call to grf_blit(), the
frm_dialog() function checks an internal pointer. If the
pointer is NULL, blitting is disabled. If the pointer is
not NULL, and the FRM_USEBLIT flag is set, frm_dialog()
calls the blit function indirectly through the pointer.
Since frm_dialog() has no direct reference to grf_blit(),
the linker won't automatically link in the blit code.
When you call this function, the pointer gets set to point
to the grf_blit() function. Since that then causes a
reference to grf_blit(), your linker does pull in all the
blit code, but only because you specifically asked it to by
coding a call to this function.
Source: aesfuncs\frmenabl.c
======================================================================
GemFast v1.8 Page 39
short frm_error(short errcode, char *buttons, char *fmt, ...)
______________________________________________________________________
Summary: Display a formatted message, followed by a standard error
message, in a dialog box.
Input: The errcode parameter is the numeric value of the error to
be reported.
The buttons parameter is a pointer to a string containing
the text of the buttons to display at the bottom of the
dialog box. Up to five buttons can be displayed. A newline
(\n) character terminates each button's text in the string
(you don't need a newline after the last button). If you
pass a NULL pointer, you get a single button labeled
"Continue".
The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: The index of the button the user clicked on to exit the
dialog, guaranteed to be in the range of 0 through 4. The
leftmost button is 0.
See Also: frm_printf() frm_defaults() frm_verror() frm_qerror()
Details: Basically, this is a frm_printf() function that adds an
error message to the end of your formatted message. This
function passes the format string and ... parameters to
sprintf() to create a formatted message. Then it passes the
errcode parameter to exterror() to get the message
describing that error, and adds it as a separate line below
the lines of your formatted message. Then it passes the
whole huge text string, along with your buttons pointer, to
frm_nldialog() for display.
Example: To report an error in opening a file, you might use:
FILE *thefile;
if (NULL == (thefile = fopen(filename, "r"))) {
return frm_error(errno, "Retry\nCancel",
"Can't open file %s",
filename);
}
Which might yield an error message dialog such as:
+--------------------------------+
| Can't open file A:\GEMFAST.DOC |
| File not found |
| |
| | Retry | | Cancel | |
+--------------------------------+
Source: aesfuncs\frmerror.c
======================================================================
GemFast v1.8 Page 40
short frm_menu(long options, OBJECT *ptree, short select_state)
______________________________________________________________________
Summary: Conduct a menu dialog using your object tree.
Input: The options parameter contains a bitmap of options as
described under Dialog Processing Options.
The ptree parameter is a pointer to the dialog tree.
The select_state parameter is the ob_state value the dialog
handler uses to indicate selection of an object.
Returns: The index of the object selected by the user, or NO_OBJECT
if the user didn't select any object.
See also: frm_defaults() frm_dsmenu() frm_nlmenu() frm_qmenu()
Details: This function conducts a menu dialog. The action of a menu
dialog is similar to that of GEM dropdown menus. The menu
items are highlighted as the mouse moves through them, so
they are called "hot buttons". (The items need not be
buttons, any type of object can be used; strings are the
most common hot button object type.)
You can use this function to implement "popup" menus that
can appear anywhere on the screen. The popup menu looks
like a regular GEM dropdown menu, a box containing strings
that highlight as the mouse moves over them, except that it
can appear anywhere on the screen. In addition to normal
popup menu dialogs, this function can conduct hybrid dialogs
that contain a mixture of normal exit buttons and menu-type
hot buttons.
For this function to work correctly, your menu dialog tree
has to be constructed with some simple rules in mind.
Objects with the EXIT, TOUCHEXIT, or DEFAULT flag bits on
will behave as normal. Objects flagged as SELECTABLE but
without the EXIT, TOUCHEXIT, or DEFAULT bits are the hot
buttons in the dialog; they will highlight as the mouse
crosses them, and a click on them will exit the dialog. The
dialog cannot contain selection (on/off) buttons, radio
buttons, or editable text fields. Objects with the DISABLED
state bit on will not highlight or cause exit if clicked.
As the mouse passes over enabled hot button objects, they
are visually selected. The value you pass for select_state
is ORed into the ob_state to visually select an object. The
most common value should be SELECTED, but in some cases
(especially with colored objects) OUTLINED is a good choice.
If the FRM_DMUSTSELECT option is used, this function will
NOT return NO_OBJECT under any circumstances; only a click
on a hot button or normal exit object will end the dialog.
======================================================================
GemFast v1.8 Page 41
Otherwise, if the user clicks on an object which is neither
a normal exit object nor a hot button, this function returns
NO_OBJECT, and if the FRM_MEXITPARENT or FRM_MEXITVICINITY
options are used and the mouse leaves the specified area,
this function returns NO_OBJECT.
If the mouse button is down on entry to this function, it
waits for the button to be released before doing anything.
When the user clicks on a TOUCHEXIT object, this function
returns with the mouse button still down, as usual. When
the user clicks on a hot button object, this function
doesn't return until the user releases the mouse button.
If the exit object was a normal EXIT or DEFAULT object, it
is deselected as per the rules for frm_dialog(). If the
exit object was a hot button, it remains selected both
visually and in the ob_state field.
Source: aesfuncs\aplmallo.c
======================================================================
GemFast v1.8 Page 42
short frm_mkmoveable(OBJECT *ptree, short mover_object)
______________________________________________________________________
Summary: Makes a dialog moveable, and designates the mover object.
Input: The ptree parameter is a pointer to the object tree.
The mover_object parameter is the index of the object in the
tree which will serve as the mover object.
Returns: The object's ob_flags value before it was modified.
See Also: frm_dialog()
Details: The frm_dialog() library routine allows users to drag a
dialog box around on the screen. Use this function to
specify the object within the dialog which serves as the
mover.
This function changes the ob_flags of the mover object,
turning off some bits and turning on others, as follows:
OFF - SELECTABLE DEFAULT EXIT EDITABLE RBUTTON HIDETREE
ON - TOUCHEXIT FRM_MOVER
It does not change bits other than those listed. The
FRM_MOVER bit is defined in GEMFAST.H.
When an object in a dialog tree is defined as the mover
object, that dialog is thereafter considered moveable on
every call to frm_dialog(), even when the FRM_MOVEABLE
option is not used in the call. The FRM_MOVEABLE dialog
option makes a dialog moveable even when this function
hasn't been called to designate the mover object. (The root
becomes the mover in that case.)
Use this function if you have designed a specific mover
object into a dialog with your resource editor. Usually a
mover object is a G_BOXTEXT object, 50%-mask gray filled,
one gl_hbox high, placed across the top of the dialog with a
title string in it. (IE, it looks like the move bar on a
window.)
Source: aesfuncs\frmmovab.c
======================================================================
GemFast v1.8 Page 43
short frm_nldialog(long options, char *buttons, char *strings)
______________________________________________________________________
Summary: Newline-delimited dialog. Builds and conducts a dialog
using the specified string and buttons.
Input: The options parameter contains a bitmap of options as
described under Dialog Processing Options.
The buttons parameter is a pointer to a string containing
the text of the buttons to display at the bottom of the
dialog box. Up to five buttons can be displayed. A newline
(\n) character terminates each button's text in the string.
If you pass a NULL pointer, you get a single button labeled
"Continue".
The strings parameter is a pointer to a string containing
the text lines for the body of the dialog. Up to 20 lines
of text can be displayed. A newline character terminates
each line's text in the string. If you pass a NULL pointer,
you get a single line containing "<no message>".
Returns: The index of the button the user clicked on to exit the
dialog, guaranteed to be in the range of 0 through 4. The
leftmost button is 0.
See Also: frm_printf() frm_defaults() frm_qtext()
Details: This function builds a dialog from the text and buttons you
specify, and conducts the dialog with the user.
You might use this function instead of frm_printf():
- If you don't need to substitute values into the output.
There is more overhead associated with frm_printf(), in
terms of memory and speed.
- If your message will exceed the 2k limit imposed by
frm_printf(). (Of course, 2k of text is more than will
fit on a standard screen.)
This is slightly a friendlier version of the frm_dsdialog()
function. Instead of constructing arrays of pointers to
strings, this allows you to use a single string with newline
characters indicating the line separations.
Example: The following example displays a dialog containing several
lines of text, and 3 buttons.
char buttons[] = "Cancel\Nignore\Nretry";
char text[] =
"\x7F" "Error!\n"
"Cannot open configuration file.\n\n"
"Please select one of these options:\n";
choice = frm_nldialog(FRM_DSL1TITLE, buttons, text);
Source: aesfuncs\frmnldia.c
======================================================================
GemFast v1.8 Page 44
short frm_nlmenu(long options, char *title, char *selections)
______________________________________________________________________
Summary: Build and conduct a menu dialog using your strings.
Input: The options parameter contains a bitmap of options as
described under Dialog Processing Options.
The title parameter is a pointer to a string which appears
in the menu dialog's title bar. If a NULL pointer is
passed, the dialog box will have no title bar.
The selections parameter is a pointer to a string containing
the menu's selectable items. Each selection is delimited by
a newline (\n) character. (You don't need a newline after
the last selection.)
Returns: The 1-based index of the item selected, or 0 if the last
item was selected, or NO_OBJECT if no item was selected.
See also: frm_defaults() frm_qmenu()
Details: This function builds and conducts a "popup" menu dialog. If
you don't need to specify any options, the frm_qmenu()
function is easier to code.
The title string (if specified) appears centered and
underlined at the top of the dialog box. The selection
strings appear, one per line, underneath the title. Any
selection string that starts with 0x7F is centered (the 0x7F
character isn't displayed). Up to 20 selection lines can be
specified. You must ensure that the title and selection
strings don't exceed the screen width.
The dialog box surrounding the title and strings will always
have a whitespace gutter of at least one character width on
each side of the widest selection line. (If the title is
wider than the widest selection, the gutter will be more
than 1 character width).
The return value behavior is a bit complex, but it makes
sense if you follow a basic rule in designing your string
dialogs: the last item on the menu should always be a Quit,
Cancel, or Exit type selection. If the user selects the
last item, the return value is 0. If the user clicks
outside the dialog, the return value is NO_OBJECT (-1).
Otherwise the return value is the 1-based index of the
selection (first line = 1, second line = 2, etc).
If you specify the FRM_DMUSTSELECT option, the user is
forced to click on a menu selection to exit. In this case,
the return value is guaranteed not to be NO_OBJECT.
Source: aesfuncs\frmnlmen.c
======================================================================
GemFast v1.8 Page 45
short frm_printf(long options, char *buttons, char *fmt, ...)
______________________________________________________________________
Summary: Formats a message, builds a dialog box around it, and
conducts the dialog.
Input: The options parameter contains a bitmap of options as
described under Dialog Processing Options.
The buttons parameter is a pointer to a string containing
the text of the buttons to display at the bottom of the
dialog box. Up to five buttons can be displayed. A newline
(\n) character terminates each button's text in the string
(you don't need a newline after the last button). If you
pass a NULL pointer, you get a single button labeled
"Continue".
The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: The index of the button the user clicked on to exit the
dialog, guaranteed to be in the range of 0 through 4. The
leftmost button is 0.
See Also: frm_defaults() frm_vprintf()
Details: This function allocates a 2k buffer to format the string
into. It passes the specified format string and ...
parameters to sprintf() to create a formatted message.
Newline (\n) characters in the result of the sprintf()
formatting delimit the lines as displayed in the dialog.
Source: aesfuncs\frmprtf.c
======================================================================
GemFast v1.8 Page 46
short frm_progress(long options, short increments,
char *button, char *fmt, ...)
______________________________________________________________________
Summary: Conducts a progress display with a thermometer bar,
formatted text, and an optional abort button.
Input: The options parameter contains a bitmap of options and
actions. The options are described under Dialog Processing
Options. In addition, you must OR in exactly one of the
following actions:
FRM_PSTART - Initialize and draw the dialog.
FRM_PUPDATE - Update the progress display.
FRM_PFINISH - Close and cleanup the dialog.
The increments parameter is interpreted differently,
depending on the action, as described below.
The button parameter is a pointer to a string containing the
text of the abort button in the dialog. If NULL, the dialog
will not contain an abort button.
The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: For FRM_PSTART, 0 on success or a negative error code.
For FRM_PUPDATE, TRUE (1) if the user clicked on the abort
button, or FALSE (0) if not.
For FRM_PFINISH, there is no return value.
See Also: frm_printf() frm_defaults() frm_vprogress()
Details: This function dynamically constructs a dialog around your
formatted text, appropriate to keeping the user informed of
the progress of some ongoing task. The dialog can
optionally contain an abort button if you want the user to
be able to abort the task. The progress can be indicated by
either or both of two methods: a graphical thermometer bar
which fills in as progress is made, and a text line in the
body of the dialog that explains the progress with words.
To start the progress dialog, use the FRM_PSTART action
flag. When you start the dialog, the increments parameter
indicates how many 'ticks' you intend to step the
thermometer bar through. If this is zero, the dialog will
not have a thermometer bar. (See the description of
xob_thermo_create() for more details on using a thermometer
bar.) If you pass a NULL button pointer when you start the
dialog, there won't be an abort button in the dialog,
otherwise the text you specify is used in the button. The
fmt parameter and values following it are processed as for
======================================================================
GemFast v1.8 Page 47
other formatted text dialogs. If you intend to use words as
well as the thermometer bar to indicate progress, the words
are displayed in place of the last line of formatted text in
the body of the dialog. It doesn't matter if the last line
is initially empty.
To update the progress display, use the FRM_PUPDATE action
flag. When updating the display, the increments parameter
can have the following values:
OBJ_TINCREMENT - Advance the thermometer bar by one.
Zero - Do not change the thermometer bar.
Greater than zero - Set the thermometer bar increment
count to the specified number.
The button parameter is ignored for FRM_PUPDATE. If the fmt
parameter is NULL, no change is made to the text in the
dialog. If non-NULL, it is a printf-style format string,
and ... arguments may follow it. In this case, the text is
formatted into a static 128-byte buffer, and is then
displayed in the last line of text in the dialog body
(replacing any existing characters on that line.) It is
your responsibility to ensure that the new line is less than
128 characters after formatting, and that it is no wider
than the widest line in the existing text. (IE, the dialog
cannot be made wider once FRM_PSTART has painted it.) If
the last line of text in the initial dialog was centered,
then all updates will be centered. (Do NOT specify the 0x7F
centering flag at the start of the update string in fmt.)
To end the dialog and remove it from the screen, use the
FRM_PFINISH action flag. All other parameters are ignored.
If you specify an abort button, be sure to check the return
value from every progress display update.
Be aware that if the FRM_MOVEABLE dialog option is in
effect, or if you specify an abort button, a progress update
call can take an indefinite amount of time. (Because the
user could spend any amount of time dragging the dialog
around or clicking but not releasing the abort exit button.)
You can update both the thermometer and text progress
display on a single call, update just one or the other, or
not update either of them. You might use the latter to poll
for an abort without changing the display when your
incremental steps take a long time.
======================================================================
GemFast v1.8 Page 48
Example: Suppose your program formats a floppy disk. You want to
report the current track and side with words, and update the
thermometer after both sides of each track are done. You
might use code such as the following:
char trackmsg[] = "Formatting Track: %d Side: %d";
char mainmsg[] = "Formatting floppy drive %c \n"
"\n" // empty line
"\x7F " // track message centered here
;
frm_progress(FRM_PSTART, ntracks, NULL, trackmsg, drive);
for (track = 0; track < ntracks; ++track) {
frm_progress(FRM_PUPDATE, 0, NULL, trackmsg, track, 0);
format_it(drive, track, 0);
frm_progress(FRM_PUPDATE, 0, NULL, trackmsg, track, 1);
format_it(drive, track, 1);
frm_progress(FRM_PUPDATE, OBJ_TINCREMENT, NULL, NULL);
}
frm_progress(FRM_PFINISH, 0, NULL, NULL);
Notice that the first line of the main dialog text contains
enough extra spaces to ensure that it will be wider than the
widest possible trackmsg display. Also notice that the last
line (where the track/side message will appear) has the \x7F
centering flag specified in the original display text, not
in the update text, and also that the \x7F is followed by a
space (since there has to be something besides the \x7F on
the line for it to be noticed as a line).
Source: aesfuncs\frmprogr.c
======================================================================
GemFast v1.8 Page 49
short frm_qchoice(char *buttons, char *fmt, ...)
______________________________________________________________________
Summary: Build and conduct dialog with formatted message and up to
five buttons.
Input: The buttons parameter is a pointer to a string containing
the text of the buttons to display at the bottom of the
dialog box. Up to five buttons can be displayed. A newline
(\n) character terminates each button's text in the string
(you don't need a newline after the last button).
The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: The index of the button the user clicked on to exit the
dialog, guaranteed to be in the range of 0 through 4. The
leftmost button is 0.
See also: frm_printf() frm_defaults() frm_qtext()
Details: This is just a frm_printf() function without an options
parameter. Think of it as an alert box with no icon and up
to five buttons.
Source: aesfuncs\frmqchoi.c
======================================================================
GemFast v1.8 Page 50
short frm_qerror(short err, char *fmt, ...)
______________________________________________________________________
Summary: Display formatted error message with Continue button.
Input: The err parameter is the numeric code of the error to be
reported.
The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: The same value passed as the err parameter.
See also: frm_printf() frm_defaults() frm_error() frm_qfatal()
Details: This is a frm_error() function with a default exit button
labeled Continue, and a different kind of return value. See
the details of frm_error() for more information on the error
message lookup and formatting.
Use frm_qerror() when the user doesn't have any corrective
action options or choices about what to do next, but the
program will continue to run.
Use frm_qfatal() when the error is so serious that the
program will shut itself down after the user acknowledges
the message.
Use frm_error() when you are able to present multiple
options (such as Cancel | Retry) to the user.
When you are just reporting an error that can't be corrected
or otherwise influenced by the user, frm_qerror() or
frm_qfatal() are better, because they return the same error
code you passed. This lets you write statements such as:
if (Success != (err = something_that_can_fail())) {
return frm_qerror(err, "Can't do something!");
}
So you can both report the error and return the error status
to the calling routine in a single statement.
Source: aesfuncs\frmqerr.c
======================================================================
GemFast v1.8 Page 51
short frm_qfatal(short err, char *fmt, ...)
______________________________________________________________________
Summary: Display formatted error message with Fatal button.
Input: The err parameter is the numeric code of the error to be
reported.
The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: The same value passed as the err parameter.
See also: frm_printf() frm_defaults() frm_error() frm_qfatal()
Details: This is a frm_error() function with a default exit button
labeled Fatal and a different kind of return value. See the
details of frm_error() for more information on the error
message lookup and formatting.
Use frm_qerror() when the user doesn't have any corrective
action options or choices about what to do next, but the
program will continue to run.
Use frm_qfatal() when the error is so serious that the
program will shut itself down after the user acknowledges
the message.
Use frm_error() when you are able to present multiple
options (such as Cancel | Retry) to the user.
When you are just reporting an error that can't be corrected
or otherwise influenced by the user, frm_qerror() or
frm_qfatal() are better, because they return the same error
code you passed. This lets you write statements such as:
if (Success != (err = something_that_can_fail())) {
return frm_qerror(err, "Can't do something!");
}
So you can both report the error and return the error status
to the calling routine in a single statement.
Source: aesfuncs\frmqerr.c
======================================================================
GemFast v1.8 Page 52
short frm_qmenu(char *title, char *selections)
______________________________________________________________________
Summary: Build and conduct a menu dialog using your strings.
Input: The title parameter is a pointer to a string which appears
in the menu dialog's title bar. If a NULL pointer is
passed, the dialog box will have no title bar.
The selections parameter is a pointer to a string containing
the menu's selectable items. Each selection is delimited by
a newline (\n) character. (You don't need a newline after
the last selection.)
Returns: The 1-based index of the item selected, or 0 if the last
item was selected, or NO_OBJECT if no item was selected.
See also: frm_defaults() frm_nlmenu()
Details: This is just a frm_nlmenu() function without an options
parameter. See the details for frm_nlmenu() for a
description of the dialog formatting. When the default
options are good enough for your popup menu, use this
function.
Source: aesfuncs\frmqmenu.c
======================================================================
GemFast v1.8 Page 53
void frm_qtext(char *fmt, ...)
______________________________________________________________________
Summary: Build and conduct dialog with formatted message and Continue
button.
Input: The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: Nothing.
See also: frm_printf() frm_defaults()
Details: This is just a frm_printf() function without options or
buttons parameters. See the details for frm_printf().
This function is especially handy for debugging GEM programs
during development, since you can easily insert calls to it:
frm_qtext("At this point, rectangle = %d %d %d %d",
*pcliprect);
But it's also useful whenever you need to communicate with
the user and the default options and a Continue exit button
are good enough.
Source: aesfuncs\frmqtext.c
======================================================================
GemFast v1.8 Page 54
short frm_question(char *fmt, ...)
______________________________________________________________________
Summary: Build and conduct a formatted dialog with Yes and No exit
buttons.
Input: The fmt parameter is a printf-style format string.
The ... parameters are values to be substituted as specified
in the format string.
Returns: FALSE (0) if the user selected No, or TRUE (1) if the user
selected Yes.
See also: frm_printf() frm_defaults()
Details: This is just a frm_printf() function without an options
parameter, and with two buttons labeled Yes and No. See the
frm_printf() for details on the message formatting.
If the FRM_DEFAULTLEFT option is in effect, the Yes button
appears on the left, and it is the default exit button.
Otherwise, the No button appears on the left, and neither
button will be a default exit button.
Source: aesfuncs\frmquest.c
======================================================================
GemFast v1.8 Page 55
void frm_sizes(OBJECT *ptree, GRECT *prect)
______________________________________________________________________
Summary: Calculate the rectangle a dialog will occupy when displayed
on the screen.
Input: The ptree parameter is a pointer to the object tree you want
the sizes of.
The prect parameter is a pointer to a GRECT structure into
which the screen location and sizes are returned.
Returns: Nothing.
See Also: obj_clcalc()
Details: This function provides the info you need to conduct the
form_dial() parts of a dialog. Normally, the form_center()
function is used to center the dialog and obtain the
resulting screen rectangle. When you want to display a
dialog that isn't centered, use this function instead of
form_center() to obtain the rectangle to pass to
form_dial().
NOTE: This function is implemented as a macro in GEMFAST.H. The
macro remaps the call to obj_clcalc(), supplying a couple
dummy parms in the process.
Source: aesfuncs\objclcal.c (via macro in GEMFAST.H)
======================================================================
GemFast v1.8 Page 56
short frm_verror(short errcode, char **buttons, char *fmt,
va_list args)
______________________________________________________________________
NOTE: This function is identical to frm_error(), except that it
takes a va_list pointer instead of directly accepting the
variable argument list. If this doesn't mean anything to
you, you probably don't need this function.
See your compiler's runtime library manual, and check out
the difference between your printf() and vprintf()
functions. That's the same as the difference between
frm_error() and frm_verror().
Source: aesfuncs\frmverro.c
short frm_vprintf(long options, char **buttons, char *fmt,
va_list args)
______________________________________________________________________
NOTE: This function is identical to frm_printf(), except that it
takes a va_list pointer instead of directly accepting the
variable argument list. If this doesn't mean anything to
you, you probably don't need this function.
See your compiler's runtime library manual, and check out
the difference between your printf() and vprintf()
functions. That's the same as the difference between
frm_printf() and frm_vprintf().
Source: aesfuncs\frmvprtf.c
short frm_vprogress(long options, short increments,
char *button, char *fmt, va_list args)
______________________________________________________________________
NOTE: This function is identical to frm_progress(), except that it
takes a va_list pointer instead of directly accepting the
variable argument list. If this doesn't mean anything to
you, you probably don't need this function.
See your compiler's runtime library manual, and check out
the difference between your printf() and vprintf()
functions. That's the same as the difference between
frm_progress() and frm_vprogress().
Source: aesfuncs\frmprogr.c
======================================================================
GemFast v1.8 Page 57
File Selector Library
The file selector library contains functions to conduct file
selector and related dialogs for you.
======================================================================
GemFast v1.8 Page 58
short fsel_exinput(char *path, char *file, short &exitbutton,
char *prompt)
______________________________________________________________________
Summary: Standard system file selector, with prompting and full
emulation on pre-TOS 1.04 systems.
Input: The inputs are identical to the standard fsel_input()
function, except that an extra parameter, prompt allows you
to provide a prompt string of up to 38 characters.
Returns: TRUE (1) if the user exited via OKAY, or FALSE (0) if the
user exited via CANCEL.
See Also:
Details: Atari added the fsel_exinput() prompted file selector
starting with TOS version 1.04. It allows you to specify a
prompt string to appear in the file selector, and it behaves
slightly differently than the original selector (saves
current default path, etc).
This implementation of fsel_exinput() is compatible with all
TOS versions. It checks the TOS version, and passes the
call directly to the AES on later versions, or emulates the
new functionality on older AES versions.
While the emulation code increases the size of your
application somewhat, the user-friendliness of the prompted
file selector is a nice feature to have. I strongly
recommend using this function rather than fsel_input().
Source: aesbind\aesfsel2.s
======================================================================
GemFast v1.8 Page 59
short fsel_sminput(char *path, char *file, short &exitbutton,
char *prompt)
______________________________________________________________________
Summary: Standard system file selector, with prompting and partial
emulation on pre-TOS 1.04 systems.
Input: The inputs are identical to the standard fsel_input()
function, except that an extra parameter, prompt allows you
to provide a prompt string of up to 38 characters.
Returns: TRUE (1) if the user exited via OKAY, or FALSE (0) if the
user exited via CANCEL.
See Also: fsel_exinput()
Details: This function is similar to fsel_exinput(), except that it
emulates only the prompting feature on older TOS versions;
other behaviors of the new file selector are not emulated.
This can make your application a bit smaller, and is
appropriate mainly for a desk accessory where a few hundred
bytes of code is significant.
Source: aesbind\aesfsel3.s
======================================================================
GemFast v1.8 Page 60
short fsl_dialog(long options, char *pfullname, char *ppath,
char *pwild, char *pprompt)
______________________________________________________________________
Summary: Conduct a complete file selector dialog, return the
resulting full device/path/file name.
Input: The options parameter specifies options as a bitmap; OR
together one or more of the following:
FSL_NORMAL - A placeholder value, equal to zero.
FSL_FNOPTIONAL - Selection of a file name is optional.
FSL_PATHONLY - Return only the path.
The pfullname parameter points to a buffer into which the
final full device/path/file name is returned. This pointer
must not be NULL.
The ppath parameter points to a buffer containing the
device/path/wildcard string to display initially in the
dialog. The final device/path/wildcard ends up in this
buffer after the call. If a NULL pointer is passed, a
default buffer internal to the function is used.
The pwild parameter, if non-NULL, points to a wildcard mask
string to be forced onto the end of the ppath string before
displaying the dialog.
The pprompt parameter points to the prompt string to display
in the file selector. If a NULL pointer is passed, a
default prompt ("Select File") is used.
Returns: TRUE (1) if the user exited via OKAY and the input passed
the validations specified in the options. FALSE (0) if the
user exited via CANCEL, or any validation failed. If this
function returns FALSE, the buffers pointed to by pfullname
and ppath are not modified.
See Also:
Details: This function simplifies file selector interaction with the
user. It is somewhat complex, because it attempts to
include all the functionality a complex program would need.
But most of the complexity is covered with simple defaults,
and the function is pretty easy to use.
If you specify the FSL_FNOPTIONAL flag, this function does
not ensure the presence of a filename in the selection made
by the user; the return value indicates only whether the
user clicked on OKAY or CANCEL. (Normally, this function
returns zero if no filename was selected; ie, a missing
filename is treated as a CANCEL.)
======================================================================
GemFast v1.8 Page 61
If you specify the FSL_PATHONLY flag, not only is the
filename entry optional, this function removes any filename
and returns just the path part. The path is guaranteed to
have a trailing '\' character.
I recommend that you use 128-character buffers to hold
pathnames. This function does no checking of pathname
lengths or truncation of long names, but 128 characters is
the accepted standard for GEMDOS programming.
About the ppath string: If this pointer is NULL, a 128-byte
static internal buffer is used instead. If the string is
empty, this function automatically initializes it to the
current device and path. If the string is not empty, is
MUST have either a wildcard string on the end of it, or a
trailing '\' character. (If it contains a path without a
wildcard or trailing '\', the last node of the pathname is
assumed to be a wildcard, and the user will get real
confused.) If it has a trailing '\', a default wildcard of
"*.*" is added.
About the pwild string: After processing the ppath string
as described above, the pwild pointer is checked. If it is
non-NULL, then the wildcard on the end of the ppath string
is replaced with the pwild string.
Once the ppath and pwild strings are processed,
fsel_exinput() is invoked. If the user selects CANCEL, this
function returns FALSE immediately. If the user selects
OKAY, the presence of a filename is verified (unless the
options say the filename is optional). If the filename
validation passes, the path and wildcard shown in the file
selector are copied to the ppath buffer. Then the full
device/path/filename string is assembled into your pfullname
buffer, and TRUE is returned.
Now we come to the religious part of this description:
usage recommendations. I hate the way folks use file
selectors in programs, and I want to establish one
overriding rule: the user should always see the same path
s/he saw last time in the file selector. That can be
modified a bit in some situations, as you'll see...
For a simple program that only deals with one type of file,
I recommend that you use a NULL ppath and pwild pointer, and
let this function do all the work. The first time you call
this function, it self-initializes to the current path.
After that, the user will always see the same thing s/he
last saw. If you want to be just a little trickier, pass an
appropriate pwild pointer the first time you call this
function, so that the user starts out seeing the right kind
of files. Then pass a NULL pwild pointer on subsequent
calls, so that if the user decided to look at a different
type of file, it stays that way.
======================================================================
GemFast v1.8 Page 62
Sometimes a program only deals with a certain kind of file.
Perhaps it can only read .RSC files, and only write .XYZ
files. In this case, use a NULL ppath pointer, but non-NULL
pwild pointers in your calls. If the user wants to try
something other than a .RSC file, it won't be prevented, but
will be strongly discouraged. However, don't do this sort
of thing if you expect to read .TXT files. Maybe the user
has renamed all the .TXT files to .DOC, and it's not your
job to discourage that by facistly forcing the wildcard on
every call.
For a complex program that deals with several types of
files, it can make sense to maintain several current paths.
Perhaps you store graphics images in one subdirectory, sound
bites in another, and script files in a third place. If the
user does a Load Image, then later does a Load Script, it
doesn't make sense to have the script file selector open up
to the image path just because that's what the user last
saw. It would make more sense to open the selector up to
the path the user saw last time s/he did something with
script files. For this situation, use a non-NULL ppath
pointer. You can have several path buffers in your program
(script_path, image_path, etc). Then just pass the same
path buffer every time you want to select that type of file,
and the user will always see the right path for that
filetype.
When you maintain several path buffers for different types
of files, you can start out with all the path buffers empty.
The first time you pass the empty buffer to this function,
it'll get initialized to the current device and path. Or,
you can pre-initialize the buffers yourself during program
startup (perhaps loading them from a config file). If you
initialize them yourself, remember to ensure that they end
in a wildcard mask or have a trailing '\' character.
The thing to avoid at all costs is using a non-NULL ppath
pointer and explicitly reloading a path into that buffer
before each call to this function. I've used programs that
explicitly loaded A:\*.* into the path before each call to
the file selector. But I never used any of them for very
long; they've all ended up in the trash.
[End of sermon]
Source: aesfuncs\fsldialo.c
======================================================================
GemFast v1.8 Page 63
Graphics Library
The graphics library contains functions to help you deal
with the graphics screen and the mouse. It includes
functions to get and set the current mouse shape, and
functions to easily blit areas of the screen from and to
memory buffers.
======================================================================
GemFast v1.8 Page 64
void gra_qmstate(short *px, short *py, short *pb)
______________________________________________________________________
NOTE: This old function is being phased out. It used Line-A to
get the mouse state, and Atari has announced the death of
Line-A. Use the standard graf_mkstate() function.
Your existing code will not break, but the new support for
this function just calls graf_mkstate(), so you might as
well convert your code.
Source: aesxbind\gramouse.c
void gra_qofmouse(void)
______________________________________________________________________
NOTE: This old function is being phased out. It used Line-A to
hide the mouse, and Atari has announced the death of Line-A.
Use the standard graf_mouse() function.
Your existing code will not break, but the new support for
this function just calls graf_mouse(), so you might as well
convert your code.
Source: aesxbind\gramouse.c
void gra_qonmouse(void)
______________________________________________________________________
NOTE: This old function is being phased out. It used Line-A to
show the mouse, and Atari has announced the death of Line-A.
Use the standard graf_mouse() function.
Your existing code will not break, but the new support for
this function just calls graf_mouse(), so you might as well
convert your code.
Source: aesxbind\gramouse.c
======================================================================
GemFast v1.8 Page 65
long grf_blit(short options, void *pbuffer, void *prect)
______________________________________________________________________
Summary: Blits a rectangle between the screen and a memory buffer.
Input: The options parameter specifies options as a bitmap. One of
the following must be specified:
GRF_BFROMSCREEN - Blit from screen to memory.
GRF_BTOSCREEN - Blit from memory to screen.
GRF_BMEMCALC - Do not blit, just calculate and return
the amount of memory required.
In addition, the following may be ORed in with the above:
GRF_BOBJTREE - The prect parameter is a pointer to an
object tree, instead of a GRECT.
The pbuffer parameter is a pointer to the memory buffer for
the blit. If the GRF_BMEMCALC flag is specified, this may
be NULL, otherwise it must not be NULL.
The prect parameter is normally a pointer to a GRECT that
describes the screen area to blit. If the GRF_BOBJTREE flag
is specified, it is a pointer to an object tree, and the
rectangle the dialog occupies on-screen is used.
Returns: The amount of memory needed to do the blit. If this value
is zero, no portion of the blit intersects the physical
screen. (IE, the blit is completely clipped.)
See Also: grf_memblit()
Details: This function simplifies the process of using blits to save
and restore portions of the screen.
If you specify the GRF_BOBJTREE flag, the prect pointer is
interpreted as a pointer to an object tree instead of a
pointer to a GRECT. In this case, the screen rectangle is
obtained using frm_sizes(prect,...), so that the object
tree's screen location is the blit area.
If you specify the GRF_BMEMCALC flag, this function
calculates and returns the size needed for a memory buffer
to do this blit, but it does not actually blit anything.
This function copies the prect rectangle to a work area and
does an rc_intersect(&gl_rfscrn, &workrect) to clip the blit
to the physical screen. (VDI tends to hang the machine if
you try to do off-screen blits.) If no portion of the
rectangle is on-screen, no blit is done, and zero is
returned. Your prect rectangle can have negative x/y
values, but it must not have negative width or height.
======================================================================
GemFast v1.8 Page 66
The memory buffer is assumed to be the right size for the
blit. The blit origin in the buffer is always 0,0. In
other words, you can't allocate a single buffer and store
several discontiguous pieces of the screen into it, you must
allocate a separate buffer for each piece of the screen you
want to save simultaneously. It is your responsibility to
use a buffer that is big enough to hold the contents of the
specified screen rectangle. (Using a buffer bigger than
necessary doesn't hurt.)
This function uses the VDI shared workstation. The mouse is
automatically hidden during the blit.
Source: aesfuncs\grfblit.c
======================================================================
GemFast v1.8 Page 67
void * grf_memblit(short options, void *pbuffer, void *prect)
______________________________________________________________________
Summary: Allocates a buffer and blits a screen area into it, or
restores the screen and frees the buffer.
Input: The options parameter specifies options as a bitmap. The
following options are available:
GRF_NORMAL - The prect parameter is a pointer to a
GRECT.
GRF_BOBJTREE - The prect parameter is a pointer to an
object tree, instead of a GRECT.
The pbuffer parameter both indicates blit direction and
specifies the buffer to use on a restore.
The prect parameter is a normally pointer to a GRECT that
describes the screen area to blit. If the GRF_BOBJTREE flag
is specified, it is a pointer to an object tree, and the
rectangle the dialog occupies on-screen is used.
Returns: A pointer to the allocated buffer. A NULL return value
indicates that a buffer could not be allocated, or the blit
area did not intersect the physical screen.
See Also: grf_blit()
Details: This function provides the easiest way to save and restore
an area of the screen.
When you pass a NULL buffer pointer, this function allocates
a buffer (of just the right size), and saves the specified
screen rectangle into it. It returns a pointer to the
allocated buffer.
To restore that screen area, call this function again,
passing the pointer it returned to you when you saved the
screen area. It restores the screen and deallocates the
buffer. (The return value in this case is garbage.)
When saving a screen area, be sure to check the returned
pointer to ensure the blit worked.
Any number of screen areas can be saved simultaneously with
multiple calls to this function, since the buffers are
dynamically allocated.
The mouse is automatically hidden during the blit.
Source: aesfuncs\grfmblit.c
======================================================================
GemFast v1.8 Page 68
short graf_mouse(short shape, void *pform)
short grf_mouse(short shape, void *pform)
______________________________________________________________________
Summary: Inquire, alter, or restore the mouse cursor shape.
NOTE: A macro in GEMFAST.H remaps graf_mouse to grf_mouse so that
your existing code need not be changed.
Input: The shape parameter specifies the action of this function.
It can have any of the standard GEM-defined values (ARROW,
BUSYBEE, M_ON, etc). In addition, there is one special
action available:
GRF_MSINQUIRE - Return information about the current
mouse shape; do not change the mouse.
The pform parameter is interpreted differently depending on
the value of the shape parameter; details below.
Returns: The shape the cursor was set to before the call, or 0 if an
error occurred. When the prior shape was ARROW, it is
handled specially; details below.
See Also:
Details: GEM doesn't provide a way to inquire what the current mouse
shape is, so this function does it for you. It keeps track
of the current mouse shape in static variables so that it
can return the value to you. Naturally, this only works if
all changes to the mouse shape are made through this
routine, so a macro in GEMFAST.H remaps your existing
graf_mouse() calls through this function.
The GEM graf_mouse() function returns zero/non-zero, and
this function is compatible with that. But, when this
function returns a non-zero value (indicating success), that
value is the shape of the mouse before call. You can use
this to temporarily change the mouse shape then restore it:
old_shape = graf_mouse(ARROW, NULL);
/* do something */
graf_mouse(old_shape, NULL);
If the old shape was ARROW (0), this function can't return
ARROW, because that would look like a failure of the call.
Instead, it returns the special value 200, defined as
GRF_MSALTARROW. When you pass GRF_MSALTARROW as the shape
parameter to this function, it is automatically translated
back to ARROW before being passed along to GEM in the real
graf_mouse() call.
If you pass the special value GRF_MSINQUIRE as the shape
parameter to this function, it returns information about the
======================================================================
GemFast v1.8 Page 69
current mouse shape without changing it. In this case, the
pform parameter is interpreted differently. If pform is
NULL, this function just returns the current shape number
without changing the shape. If you pass a non-NULL pform
with GRF_MSINQUIRE, it is a pointer to a pointer variable
into which the current user-defined form pointer is stored.
This feature is used as follows:
void *oldform;
short oldshape;
oldshape = graf_mouse(GRF_MSINQUIRE, &oldform);
graf_mouse(USER_DEF, myform);
/* do something with your custom mouse form */
graf_mouse(oldshape, oldform);
You only need to use this technique if you are going to
change the shape to your own user-defined shape. If the
mouse was a user-defined shape, and you change it to a
standard system shape, then graf_mouse(oldshape, NULL) will
restore the prior user-defined shape properly.
Source: aesfuncs\grfmouse.c
======================================================================
GemFast v1.8 Page 70
Menu Library
The menu library contains functions which help you manage
the GEM menu bar. It contains several functions that exist
primarily to support GemFast internals, and several things
which provide functionality GEM doesn't give you directly.
Use of any of these functions other than menu_bar() might
make your program incompatible with MultiTOS. I don't know
this for sure, if someone can verify it, please tell me.
======================================================================
GemFast v1.8 Page 71
short menu_bar(OBJECT *ptree, short on_off_flag)
short mnu_bar(OBJECT *ptree, short on_off_flag, long reserved)
______________________________________________________________________
Summary: Turn the menu bar on or off in a way that it can
transparently enabled and disabled.
NOTE: A macro in GEMFAST.H remaps menu_bar to mnu_bar so that your
existing code need not be changed.
Input: The ptree parameter is a pointer to the object tree
describing the menu.
The on_off_flag parameter indicates whether you are turning
the specified menu on (ie, installing it), or turning it off
(removing it).
The reserved parameter is for future use, and must be zero.
(The menu_bar() macro supplies the zero.)
Returns: Zero for failure or non-zero for success.
See Also: mnu_enable() mnu_disable()
Details: This function helps implement menus that can be temporarily
disabled. There are times when a library routine wants to
disable menu processing without disabling window controls as
well (in other words, wind_update() is sometimes too
strong). GEM's menu_bar(whatever,0) function can disable
the menu, but then you have to have the pointer to the menu
tree available to re-enable it.
This function simply remembers the menu tree pointer when
the application turns on its menu. This allows the related
mnu_enable() and mnu_disable() functions to make menu_bar()
calls to turn the menu on and off using whatever menu tree
was last supplied by the application.
This works because menu_bar(whatever, 0) disables menu
processing, but does not actually erase the menu from the
screen. If GEM's menu_bar() ever starts erasing the menu
visually, I'm going to have a lot of kludging to do.
Source: aesfuncs\mnubar.c
======================================================================
GemFast v1.8 Page 72
void mnu_disable(void)
______________________________________________________________________
Summary: Disable the menu bar from responding to the mouse.
Input: Nothing.
Returns: Nothing.
See Also: mnu_enable() mnu_bar()
Details: This function prevents the menu bar from responding to the
mouse, but it does not also disable window controls like
wind_update() does. It works like hide/show mouse calls, in
that 3 calls to mnu_disable() will require 3 calls to
mnu_enable() to get the menus active again.
Source: aesfuncs\mnubar.c
======================================================================
GemFast v1.8 Page 73
void mnu_enable(void)
______________________________________________________________________
Summary: Re-enable the menu bar to respond to the mouse.
Input: Nothing.
Returns: Nothing.
See Also: mnu_disable() mnu_bar()
Details: This function allows the menu bar to begin responding to
mouse events again after it had been disabled. It works
like hide/show mouse calls, in that 3 calls to mnu_disable()
will require 3 calls to mnu_enable() to get the menus active
again.
Source: aesfuncs\mnubar.c
======================================================================
GemFast v1.8 Page 74
void mnu_erase(void)
______________________________________________________________________
Summary: Turn of the menu bar and remove it from the screen.
Input: Nothing.
Returns: Nothing.
See Also: mnu_tbar()
Details: This function turns off the current menu (if any), and
erases the menu bar area of the screen.
Source: aesfuncs\mnutbar.c
======================================================================
GemFast v1.8 Page 75
void mnu_tbar(char *title)
______________________________________________________________________
Summary: Turn of the menu bar and display a text string in its place.
Input: The title parameter is a pointer to the string to be
displayed in the menu bar.
Returns: Nothing.
See Also: mnu_erase()
Details: This function turns off the current menu (if any), and
displays the specified string centered in the menu bar area
of the screen.
Example: If your program allows the user to "shell out" to other
programs, you can use this function to display the name of
the program before executing it, like the GEM desktop does:
void exec_a_program(char *fname)
{
static char fullpath[128];
strcpy(fullpath, fname);
if (!shel_find(fullpath))
return frm_qerror(-33, "Can't exec program");
graf_mouse(BEE, NULL); // make mouse a BEE, and put
mnu_tbar(fullpath); // program name in menu bar.
Pexec(0, fullpath, "\0", NULL);
menu_bar(my_normal_menu,1); // restore our menu bar, and
graf_mouse(ARROW, NULL); // make sure mouse is ARROW.
return Success;
}
Source: aesfuncs\mnutbar.c
======================================================================
GemFast v1.8 Page 76
Object Library
The object library contains functions which manipulate an
object in a tree. There are functions for getting and
setting most of the common object structure fields.
Directly accessing the fields in an object, especially the
ob_spec field, is becoming an increasingly dangerous thing
to do when using GemFast. The extended object library now
implements a variety of new objects, or modifies the
behavior or existing objects, and this is largely done by
'hooking' the objects through their ob_type and ob_spec
fields. (The high byte of ob_type, the so-called 'extended
object type field' is never touched by GemFast internals,
but the low byte is often changed to a G_USERDEF type, and
the original type is moved into the XUSERDEF block attached
to the object via its ob_spec field.)
Note that GemFast never modifies objects other than when you
specifically direct it to, by calling one of the functions
that transforms an existing object into an extended object.
Still, inasmuch as you may decide at a later date to
transform an object, it is safest to use the access
functions to get at ob_type and ob_spec values.
GemFast internals never modify an object's INDIRECT flag;
that is left as a method for an application to 'hook' the
object. All GemFast internals do correctly handle objects
with the INDIRECT flag set, so you may use the INDIRECT flag
yourself to tie your own extra data to an object.
Because the value associated with an object may be
indirected through a G_USERDEF and/or INDIRECT flag, it is
best to use the object library functions to access the
values associated with an object. These values can be
strings, numbers, or pointers to GemFast-defined structures.
The following functions are provided as a safe way to
manipulate an object's associated values:
obj_gstring() - Get object's string pointer.
obj_sstring() - Set object's string pointer.
obj_gvalue() - Get object's numeric value.
obj_svalue() - Set object's numeric value.
obj_gtype() - Get object's basic ob_type.
Several functions which used to be in the object library
have been moved to the extended object library, and now have
an xob_ prefix. These functions are still accepted via
their former obj_ names as well. The functions are:
obj_mkthermo -> xob_thermo_create
obj_udthermo -> xob_thermo_update
obj_mxuserdef -> xob_transform
======================================================================
GemFast v1.8 Page 77
short obj_bmbuttons(OBJECT *ptree, short parent, short select_state,
short newbits)
______________________________________________________________________
Summary: Translate a group of buttons with extended type info into a
bitmap-vector or vice versa.
Input: The ptree parameter is a pointer to the tree containing the
button group.
The parent parameter is the index of the object which is the
direct parent of the group of buttons.
The select_state parameter is a mask of ob_state bits used
to select an object.
The newbits parameter contains the bitmap to be translated
into selected buttons, or it contains the special value
OBJ_BMINQUIRE which indicates that you want to get the
bitmap describing the selected buttons without changing the
button states.
Returns: A bitmap of the buttons that were selected before the call.
See also: rsc_sxtypes() obj_xtfind()
Details: This function is useful when you have a group of buttons in
a dialog which represent on/off options that your program
can handle. When your program supports a variety of
options, a common technique is to use bits within a word to
represent the options. (Like the options in the GemFast
forms library.) This function helps you translate the state
of the dialog buttons to and from the bitmapped
representation used within your program.
The extended object type field is the upper 8 bits of the
ob_type field in an object. These bits are always available
to your program for any use you want. By setting the
extended object types for a collection of buttons to the
values representing your bitmapped options, you can easily
relate each button to the option it represents within your
program. Up to 8 options can be encoded in a group of
buttons in this way. If you need more than 8 options, just
use more than one parent object, and put 8 buttons in each
parent. (The parent can be an IBOX so that the user doesn't
know you've performed any arbitrary grouping.) Some
resource editors let you specify the extended object type
when you define your dialog. If yours doesn't, just use the
rsc_sxtypes() function during program startup.
When you pass a newbits value of OBJ_BMINQUIRE, this
function checks each object within the parent. It ANDs each
object's ob_state field with the select_state parameter, and
if the result is non-zero, it ORs the object's extended
======================================================================
GemFast v1.8 Page 78
object type into the return value. The return value is the
bitmap of all extended type values for objects that were in
a selected state.
When you pass any value other than OBJ_BMINQUIRE for the
newbits parameter, this function changes the state of the
objects as well as returning the old-state bitmap. In this
case, it again checks each object within the parent, but it
ANDs the newbits with the extended object type of each
object. When the result is non-zero, it ORs the
select_state value into the object's ob_state; when the
result is zero, it ANDs ~select_state with the object's
ob_state. This results in selecting all buttons which
represent 1 bits in the newbits parameter, and deselecting
all buttons which represent 0 bits in newbits.
Note that the objects don't have to be buttons; this
function keys off of the extended object type and state
fields only.
Example: Suppose your program has four options, and a dialog box that
lets users turn each of those options on or off with
selection (ie, non-radio) buttons. The following code
======================================================================
GemFast v1.8 Page 79
fragments illustrate how this function helps:
#define AUTOSAVE 0x0001
#define AUTOBACKUP 0x0002
#define FILEOUTPUT 0x0004
#define PRINTOUTPUT 0x0008
short options = AUTOSAVE | FILEOUTPUT; // defaults
OBJECT *option_dialog;
void prog_init()
{
appl_init();
rsrc_load(etc, etc);
rsc_gtrees(OPTIONDIALOG, &option_dialog, -1);
/*
* set button extended types to our bit values...
*/
rsc_sxtypes(option_dialog,
AUTOSAVE_BUTTON, AUTOSAVE,
AUTOBACK_BUTTON, AUTOBACKUP,
FILEOUT_BUTTON, FILEOUTPUT,
PRTOUT_BUTTON, PRINTFOUTPUT,
-1);
}
void do_options_dialog()
{
/*
* translate current options to selected buttons...
*/
obj_bmbuttons(option_dialog,
BUTTON_PARENT, SELECTED, options);
/*
* do dialog...
*/
frm_dialog(FRM_CENTER, option_dialog, 0);
/*
* translate buttons now selected back into options
* variable...
*/
options = obj_bmbuttons(option_dialog,
BUTTON_PARENT, SELECTED, OBJ_BMINQUIRE);
}
Source: aesfuncs\objbmbtn.c
======================================================================
GemFast v1.8 Page 80
short obj_clcalc(OBJECT *ptree, short object, GRECT *pgrect,
VRECT *pvrect)
______________________________________________________________________
Summary: Calculates a clipping rectangle for an object.
Input: The ptree parameter is a pointer to the tree containing the
object.
The object parameter is the index of the object to be
calculated.
The pgrect parameter is a pointer to a GRECT structure into
which the results are returned. If this is NULL, the
results are not returned in GRECT format.
The pvrect parameter is a pointer to a VRECT structure into
which the results are returned. If this is NULL, the
results are not returned in VRECT format.
Returns: The adjustment applied to the object's basic rectangle to
arrive at the on-screen rectangle. Always zero or greater.
(EG, a value of 4 indicates that the returned rectangle is 4
pixels larger on all sides than the rectangle described by
the object's xywh values.)
See Also: frm_sizes()
Details: This function calculates the rectangle that an object
occupies on the screen. It understands that some objects
have an on-screen size larger than their xywh values imply.
(IE, when the object is OUTLINED, SHADOWED, etc).
If you want to calculate the rectangle for an entire tree,
the frm_sizes() function is easier to code.
Do not count on this function for absolute precision. The
calculated rectangle will fully enclose the object, but it
might be a pixel or two larger than the visual boundary of
the object. (This is because of the arcane rules for
SHADOWED objects in particular.) So this function will
always work if you want to save the screen under the object;
you may just save a couple pixels more than you need to.
But, it may not be sufficient if you want to accurately
outline the object with a box drawn via VDI calls, for
example.
Prior GemFast docs stated that this function was obsolete
and was being phased out. Instead of obsoleting it, I threw
away the buggy old assembler code and rewrote it in C. I
don't plan to phase it out anymore.
Source: aesfuncs\objclcal.c
======================================================================
GemFast v1.8 Page 81
void obj_flchange(OBJECT *ptree, short object, short newflags,
short drawflag [ ,GRECT *cliprect ])
______________________________________________________________________
Summary: Change an object's flags, with optional redraw.
Input: The ptree parameter is a pointer to the tree containing the
object to change.
The object parameter is the index of the object to change.
The newflags parameter specifies which object flag bits to
change; details below.
The drawflag parameter specifies whether the object is to be
visually updated on the screen, use one of the following:
OBJ_NODRAW (0) - Don't update the screen.
OBJ_WITHDRAW (1) - Update the screen.
OBJ_CLIPDRAW (2) - Update the screen with clipping.
The cliprect parameter is an optional pointer to a rectangle
which will be used to clip the redraw of the object. This
parameter is only used when the drawflag parameter is equal
to OBJ_CLIPDRAW.
Returns: Nothing.
See Also:
Details: This function provides a simple way to change the object
flag bits for any object.
If the high bit of the newflags parameter is set, an AND is
used to mask off bits in the object flags. If the high bit
is not set, an OR is used to set bits in the object flags.
This allows a newflags value of DEFAULT to set the default
bit, and a value of ~DEFAULT to unset it.
When the drawflag parameter is non-zero, an objc_draw() call
is automatically done after the flags are changed. The
objc_draw() is always done starting at the root object and
drawing to MAX_DEPTH, and the draw is clipped to the on-
screen rectangle of the object being changed. This allows a
change that sets HIDETREE to properly hide the object
visually, because the parent of the object is redrawn, but
the object itself is not.
When your dialog is in a window and you need to clip the
redraw, use the OBJ_CLIPDRAW option, and provide a pointer
to the clipping rectangle. If the draw option is not
CLIPDRAW, the clip pointer need not be specified.
Source: aesfuncs\objflchg.c
======================================================================
GemFast v1.8 Page 82
char * obj_gstring(OBJECT *ptree, short object)
______________________________________________________________________
Summary: Obtain an object's string pointer.
Input: The ptree parameter is a pointer to the tree containing the
object.
The object parameter is the index of the object.
Returns: Pointer to object's associated string.
See Also: rsc_sstrings() obj_sstring() obj_gvalue() obj_svalue()
Details: This function gets a string pointer which is associated with
a string-related object.
In standard GEM programming, an object's ob_spec field
points to the string. In GemFast, however, an increasing
number of extended objects have their string pointers stored
in an extension block, and the object's ob_spec points at
the extension block.
This function understands how to find the real string
pointer for all string-related object types. It copes with
the INDIRECT flag. It understands extended G_USERDEF
objects, where ob_spec has been moved into the XUSERBLK.
When an object is not string-related, the obj_gvalue()
function should be used instead of this function.
Source: aesfuncs\objppstr.c
======================================================================
GemFast v1.8 Page 83
short obj_gtype(OBJECT *ptree, short object)
______________________________________________________________________
Summary: Obtain an object's ob_type.
Input: The ptree parameter is a pointer to the tree containing the
object.
The object parameter is the index of the object.
Returns: The basic ob_type of the object.
See Also:
Details: This function obtains an object's basic ob_type value. If
the object has any extended object type in the high byte of
its ob_type field, that information is NOT returned. (It is
always safe to access the extended object type stored in the
high byte of an object's ob_type field directly, since
GemFast internals never touch that byte.)
This function understands extended object types, where the
original ob_type is either GemFast-defined or has been moved
into the XUSERBLK structure attached to the object. For
these types of objects, it returns the actual object type,
not the G_USERDEF type found by looking directly at the
ob_type field.
Source: aesfuncs\objgtype.c
======================================================================
GemFast v1.8 Page 84
long obj_gvalue(OBJECT *ptree, short object)
______________________________________________________________________
Summary: Obtain an object's associated value.
Input: The ptree parameter is a pointer to the tree containing the
object.
The object parameter is the index of the object.
Returns: The value associated with the object.
See Also: obj_svalue() obj_gstring() obj_sstring()
Details: This function obtains the value which is associated with an
object.
In standard GEM programming, an object's ob_spec field holds
the object's value, which is usually related to drawing the
value in some way. In GemFast, however, a number of
extended objects have numeric values associated with them
which are stored in an extension block, and the object's
ob_spec points at the extension block.
When an object is string-related, the obj_gstring() function
should be used instead of this function.
Source: aesfuncs\objgspec.c
======================================================================
GemFast v1.8 Page 85
void obj_offxywh(OBJECT *ptree, short object, GRECT *prect)
______________________________________________________________________
Summary: Get the screen-adjusted xywh values for an object.
Input: The ptree parameter is a pointer to the object tree.
The object parameter is the index of the object.
The prect parameter is a pointer to the rectangle into which
the object's xywh values are returned.
Returns: Nothing.
See Also: obj_clcalc()
Details: This function gets the screen-adjusted xywh values for the
object. It does NOT take into account that some objects are
visually larger than their xywh values imply (ie, OUTLINED
objects). Use the obj_clcalc() function if you need to
account for the actual visual area an object occupies on the
screen.
Source: aesfuncs\objoxywh.c
======================================================================
GemFast v1.8 Page 86
short obj_parent(OBJECT *ptree, short object)
______________________________________________________________________
Summary: Return the parent object for the specified object.
Input: The ptree parameter is a pointer to the object tree.
The object parameter is the index of the object.
Returns: The index of the parent object.
See Also:
Details: By definition, the root object has no parent. If you try to
get the parent of the root, zero is returned, as if the root
were its own parent.
Source: aesfuncs\objrbutl.c
======================================================================
GemFast v1.8 Page 87
char ** obj_ppstring(OBJECT *pobj)
______________________________________________________________________
Summary: Return a pointer to an object's string pointer.
Input: The pobj parameter is a pointer to the object.
Returns: A pointer to the object's string pointer. Undefined if the
object isn't string-related.
See Also: rsc_gstrings() rsc_sstrings() obj_gstring() obj_sstring()
Details: This routine exists primarily to support other library
routines, but you can use it directly. It returns a pointer
to the string pointer for a string-related object. String-
related objects and the pointers this finds for each are:
G_STRING The ob_spec string pointer.
G_BUTTON The ob_spec button-text pointer.
G_TITLE The ob_spec title-text pointer.
G_TEXT The te_ptext pointer.
G_FTEXT The te_ptext pointer.
G_BOXTEXT The te_ptext pointer.
G_FBOXTEXT The te_ptext pointer.
G_ICON The ib_ptext pointer.
G_TSCOLL The currently-selected string.
This function understands how to find the real string
pointer for each of these object types. It copes with the
INDIRECT flag. It understands extended G_USERDEF objects,
where ob_spec has been moved into the XUSERBLK.
If you're not used to working with double-indirect pointers,
I recommend that you consider using one of the functions
listed under See Also, above.
Source: aesfuncs\objppstr.c
======================================================================
GemFast v1.8 Page 88
short obj_rbfind(OBJECT *ptree, short parent, short rbstate)
______________________________________________________________________
Summary: Finds the selected button in a group of radio buttons.
Input: The ptree parameter is a pointer to the object tree.
The parent parameter is the index of the parent which
contains the radio buttons.
The rbstate parameter is the ob_state mask to look for.
Returns: The index of the selected object, or NO_OBJECT (-1) if no
radio buttons are in the desired state.
See Also: obj_rbselect()
Details: This function walks through the children of the specified
parent. For each child object with the RBUTTON bit set in
the ob_flags, it does an AND of the child's ob_state against
the rbstate parameter. It returns the index of the first
child object which has a non-zero result from the AND. It
returns NO_OBJECT if the result was zero for all children.
The most common use of this function is to pass SELECTED for
the rbstate parameter. Sometimes it's handy to use OUTLINED
or another state to indicate selection of an object, so this
function allows any state bit(s) to be specified. If you
pass a combination of bits, (ie, (SELECTED|OUTLINED)), then
this function finds the first radio button with either (not
both) of those bits set.
Source: aesfuncs\objrbutl.c
======================================================================
GemFast v1.8 Page 89
short obj_rbselect(OBJECT *ptree, short selobj, short selstate)
______________________________________________________________________
Summary: De-selects current radio button, selects a new one.
Input: The ptree parameter is a pointer to the object tree.
The selobj parameter is the index of the new radio button to
be selected.
The selstate parameter specifies the ob_state bits which are
turned off in the current radio button and turned on in the
new one.
Returns: The index of the radio button that was selected before the
call, or NO_OBJECT if no buttons were previously selected.
See Also: obj_rbfind()
Details: This function is the easiest way to set a given radio button
to a selected state. If a button in the group is already
selected, this function de-selects it before selecting the
new button.
Note that this function does NOT update the buttons on-
screen, it only changes the ob_state words. Use this for
setting up a dialog before displaying it. After that, the
GEM forms manager updates the ob_state and the on-screen
object during dialog processing.
Source: aesfuncs\objrbutl.c
======================================================================
GemFast v1.8 Page 90
void obj_sstring(OBJECT *ptree, short object, char *newstring)
______________________________________________________________________
Summary: Change an object's string pointer.
Input: The ptree parameter is a pointer to the tree containing the
object to change.
The object parameter is the index of the object to change.
The newstring parameter is a pointer to a string which is to
be attached to the object.
Returns: Nothing.
See Also: rsc_sstrings() obj_gstring() obj_gvalue() obj_svalue()
Details: This function attaches a string pointer to a string-related
object.
In standard GEM programming, an object's ob_spec field
points to the string. In GemFast, however, an increasing
number of extended objects have their string pointers stored
in an extension block, and the object's ob_spec points at
the extension block.
This function understands how to find the real string
pointer for all string-related object types. It copes with
the INDIRECT flag. It understands extended G_USERDEF
objects, where ob_spec has been moved into the XUSERBLK.
When an object is not string-related, the obj_svalue()
function should be used instead of this function.
Source: aesfuncs\objppstr.c
======================================================================
GemFast v1.8 Page 91
void obj_stchange(OBJECT *ptree, short object, short newstate,
short drawflag [, GRECT *cliprect ])
______________________________________________________________________
Summary: Change an object's state, with optional redraw.
Input: The ptree parameter is a pointer to the tree containing the
object to change.
The object parameter is the index of the object to change.
The newstate parameter specifies which object state bits to
change; details below.
The drawflag parameter specifies whether the object is to be
visually updated on the screen, use one of the following:
OBJ_NODRAW (0) - Don't update the screen.
OBJ_WITHDRAW (1) - Update the screen.
OBJ_CLIPDRAW (2) - Update the screen with clipping.
The cliprect parameter is an optional pointer to a rectangle
which will be used to clip the redraw of the object. This
parameter is only used when the drawflag parameter is equal
to OBJ_CLIPDRAW.
Returns: Nothing.
See Also:
Details: This function provides a simple way to change the object
state bits for any object.
If the high bit of the newstate parameter is set, an AND is
used to mask off bits in the object flags. If the high bit
is not set, an OR is used to set bits in the object flags.
This allows a newstate value of SELECTED to set the bit, and
a value of ~SELECTED to unset it.
When the drawflag parameter is non-zero, an objc_draw() call
is automatically done after the flags are changed. The
objc_draw() is always done starting at object and drawing to
MAX_DEPTH, and the draw is clipped to the on-screen
rectangle of the dialog that contains it.
When your dialog is in a window or another situation in
which you might need to clip the redraw, use the
OBJ_CLIPDRAW option, and provide a pointer to the clipping
rectangle. If the draw option is not CLIPDRAW, the clip
pointer need not be specified.
Source: aesfuncs\objstchg.c
======================================================================
GemFast v1.8 Page 92
void obj_svalue(OBJECT *ptree, short object, long newvalue)
______________________________________________________________________
Summary: Change an object's associated value.
Input: The ptree parameter is a pointer to the tree containing the
object to change.
The object parameter is the index of the object to change.
The newvalue parameter is a longword value to be stored with
the object.
Returns: Nothing.
See Also: obj_gvalue() obj_gstring() obj_sstring()
Details: This function sets a new value to be associated with an
object.
In standard GEM programming, an object's ob_spec field holds
the object's value, which is usually related to drawing the
value in some way. In GemFast, however, a number of
extended objects have numeric values associated with them
which are stored in an extension block, and the object's
ob_spec points at the extension block.
When an object is string-related, the obj_sstring() function
should be used instead of this function.
Note that this function does NOT trigger an automatic update
in the appearance of an object that is currently on-screen;
a separate objc_draw() call would be required to do that.
Source: aesfuncs\objgspec.c
======================================================================
GemFast v1.8 Page 93
short obj_xtfind(OBJECT *ptree, short parent, short xtype)
______________________________________________________________________
Summary: Finds the object with the specified extended object type.
Input: The ptree parameter is a pointer to the tree.
The parent parameter is the index of the parent which
contains the objects to be scanned.
The xtype parameter specifies the extended object type to
search for.
Returns: The index of the object having the specified extended type,
or NO_OBJECT (-1) if nothing was found.
See Also: obj_bmbuttons() rsc_sxtypes()
Details: This function scans the children of the specified parent
object. It compares the extended object type in each child
to the specified xtype, and returns the index of the first
object which matches. If none of the children have the
specified extended type, NO_OBJECT is returned.
Extended object types are stored in the upper byte of the
ob_type word. GEM only uses the lower 8 bits of the ob_type
value, and ignores any value in the upper 8 bits. All
GemFast library routines which look at or set the ob_type
field also work with the lower 8 bits, and ignore (or
preserve) the upper 8 bits.
So, you can stuff any 8-bit value you want into the upper 8
bits of the ob_type word. There's a zillion things you can
do with it.
Source: aesfuncs\objxtfind.c
======================================================================
GemFast v1.8 Page 94
void obj_xywh(OBJECT *ptree, short object, GRECT *prect)
______________________________________________________________________
Summary: Get the xywh values for an object.
Input: The ptree parameter is a pointer to the object tree.
The object parameter is the index of the object.
The prect parameter is a pointer to the rectangle into which
the object's xywh values are returned.
Returns: Nothing.
See Also: obj_offxywh() obj_clcalc()
Details: This function gets the xywh values for the object. The
values returned are straight from the object; they are
relative to the object's parent, not to the screen.
Source: aesfuncs\objoxywh.c
======================================================================
GemFast v1.8 Page 95
Miscellanious Utilities Library
The miscellanious utilities library contains functions which
are commonly used to perform standard calculations used in
GEM programming. It also includes several function-like
macros that let you use shorthand notation to perform common
actions.
In reading the descriptions of the rectangle calculation
functions, it is important to keep in mind that these
functions never affect pixels; they work only with the
rectangle structures that describe areas of pixels.
(Sometimes the wording gets confusing. "Copies a rectangle"
means the xywh values are copied, not the pixels the
rectangle describes.)
======================================================================
GemFast v1.8 Page 96
void rc_confine(void *boundrect, void *destrect)
______________________________________________________________________
Summary: Confine a rectangle to the inside of another rectangle.
Input: The boundrect parameter is a pointer to the boundary
rectangle within which the destination is confined.
The destrect parameter is a pointer to the destination
rectangle. This rectangle supplies input values and
receives the results of the calculation; details below.
Returns: Nothing.
See Also: frm_confine()
Details: This function forces the destination rectangle to be
confined within the boundary rectangle.
On entry, the destination rectangle describes an initial
xywh area. If any part of that area is outside the boundary
rectangle, the x and y values of the destination are
adjusted to keep it within the boundary.
The width and height of the destination are never changed.
It assumed (but not at all required) that the destination
rectangle will fit within the boundary.
If the destination rectangle is wider or taller than the
boundary, it is aligned with the upper or left corner of the
boundary in that dimension. In other words, if the boundary
were the physical screen, the x/y values would never be set
to negative values. This allows you to call this function
to align rectangle then call rc_intersect() to clip if
clipping is a requirement.
Example: Suppose you want to center a window over the current mouse
location. You get the mouse x/y and set the window
rectangle's x/y so that it's centered over the mouse
location. If the mouse was near the edge of the screen, the
window's xywh might now describe some off-screen area, so
you do:
rc_confine(&gl_rwdesk, &windrect);
winx_set(whandle, WF_CURRXYWH, &windrect);
This forces the edges of the window to align with the
desktop if the window would have been partly off-screen
before the call. You know the window isn't bigger than the
desktop, so this sequence will always force the entire
window to appear on-screen.
Source: aesfuncs\rcconfin.c
======================================================================
GemFast v1.8 Page 97
void rc_copy(void *sourcerect, void *destrect)
______________________________________________________________________
Summary: Copy the source rectangle to the destination rectangle.
Input: The sourcerect parameter is a pointer to the source
rectangle.
The destrect parameter is a pointer to the destination
rectangle.
Returns: Nothing.
See Also:
Details: This copies a rectangle, or more accurately, 8 bytes of
word-aligned data.
Source: aesfuncs\rccopy.c
======================================================================
GemFast v1.8 Page 98
int rc_equal(void *rect1, void *rect2)
______________________________________________________________________
Summary: Returns TRUE if two rectangles are identical.
Input: The rect1 and rect2 parameters are pointers to the
rectangles to be compared.
Returns: TRUE (non-zero) if the rectangles are identical, FALSE (0)
if they're not.
See Also:
Details: For the rectangles to be identical, all four values (xywh)
must be equal. More accurately, this function compares 8
bytes of word-aligned data.
Source: aesfuncs\rcequal.c
======================================================================
GemFast v1.8 Page 99
GRECT * rc_gadjust(GRECT *prect, short hadjust, short vadjust)
______________________________________________________________________
Summary: Adjust the size of a GRECT rectangle.
Input: The prect parameter is a pointer to the rectangle to be
adjusted.
The hadjust parameter is the number of pixels to adjust by
in the horizontal direction. Positive values enlarge the
rectangle; negative values shrink it.
The vadjust parameter is the number of pixels to adjust by
in the vertical direction. Positive values enlarge the
rectangle; negative values shrink it.
Returns: The pointer to the rectangle.
See Also: rc_vadjust()
Details: This function makes a GRECT rectangle describe a larger or
smaller area. The rectangle remains centered on its
original location, and grows or shrinks equally on each side
in the adjusted dimension(s).
The x/y locations are never allowed to go negative (they are
clipped to zero). The w/h sizes are never allowed to fall
below 1.
Source: aesfuncs\rcadjust.c
======================================================================
GemFast v1.8 Page 100
VRECT * rc_gtov(GRECT *pgrect, VRECT *pvrect)
______________________________________________________________________
Summary: Convert a GRECT rectangle to a VRECT rectangle.
WARNING: There was a major change in this function's behavior in v1.8
that will affect existing code; details below.
Input: The pgrect parameter is a pointer to the source GRECT.
The pvrect parameter is a pointer to the destination VRECT.
Returns: The pointer to the destination VRECT.
See Also: rc_vtog()
Details: The source GRECT is converted to the equivalent VRECT. Do
NOT specify the same rectangle for source and destination.
A GRECT describes an area by x, y, width and height. A
VRECT describes an area by the x and y coordinates of
diagonally opposite corners. This function translates a
GRECT to a VRECT as follows:
pvrect->v_x1 = pgrect->g_x;
pvrect->v_y1 = pgrect->g_y;
pvrect->v_x2 = pgrect->g_x + pgrect->g_w - 1;
pvrect->v_y2 = pgrect->g_y + pgrect->g_h - 1;
GemFast versions prior to v1.8 did not apply the -1
correction to the second pair of coordinates. This was just
plain wrong, and it had to be fixed even though you may now
have to go remove some -1 expressions in your existing code
where you were compensating for the broken behavior of the
old versions. ::sigh:: Sorry.
Source: aesfuncs\rcgtov.c
======================================================================
GemFast v1.8 Page 101
int rc_intersect(GRECT *sourcerect, GRECT *destrect)
______________________________________________________________________
Summary: Calculate the intersecting portion of two rectangles.
WARNING: There was a minor change in this function's behavior in v1.8
that could affect existing code; details below.
Input: The sourcerect parameter is a pointer to the source (or
clipping) rectangle.
The destrect parameter is a pointer to the destination
rectangle. The destination rectangle is used for input and
output.
Returns: TRUE (1) if the two rectangles intersect, or FALSE (0) if
they do not intersect. When the return value is FALSE, the
contents of the destination rectangle are undetermined.
See Also:
Details: You can think of this function as clipping the destination
rectangle against the area of the source.
On entry, the destination rectangle describes an area that
may or may not have pixels in common with the source (or
clipping) rectangle. This function modifies the destination
rectangle to describe the area where the two rectangles
intersect. If they don't intersect at all, this function
returns FALSE, and the destination rectangle is left in an
undetermined state.
This function is typically used in window redraw loops, to
process the window rectangle list. It can also be used in
general-purpose drawing situations, especially to generate a
clip rectangle to keep a blit from going outside the window
work area or off the screen.
This function does NOT clip to the physical screen
automatically. Negative values in the returned x and y
coordinates are possible if negative values existed in the
inputs.
In GemFast versions prior to v1.8, this function would
return TRUE if the destination rectangle had a zero width or
height. That doesn't make sense; if width or height is
zero, there's obviously no intersection of the two
rectangles (they may abut rather than intersect). Starting
with v1.8, a zero width or height results in a FALSE return
value. This shouldn't break any existing code (and should
make your window redraw loops a bit simpler) but as a change
in behavior it bears mentioning.
Source: aesfuncs\rcinters.c
======================================================================
GemFast v1.8 Page 102
short rc_ptinrect(GRECT *prect, short x, short y)
______________________________________________________________________
Summary: Determine whether a point is inside a rectangle.
Input: The prect parameter is a pointer to the rectangle.
The x and y parameters are the coordinates of the point to
be checked against the rectangle.
Returns: TRUE if the point is inside the rectangle, FALSE if not. A
point on the boundary of the rectangle is considered to be
inside it.
See Also:
Details: This is useful for determining whether the mouse is
currently located within some arbitrary area.
Source: aesfuncs\rcptinre.c
======================================================================
GemFast v1.8 Page 103
GRECT * rc_scale(GRECT *sourcerect, GRECT *destrect, short percent)
______________________________________________________________________
Summary: This function calculates a scaled copy of a rectangle.
Input: The sourcerect parameter is a pointer to the source
rectangle.
The destrect parameter is a pointer to the destination
rectangle.
The percent parameter is the scaling factor.
Returns: The pointer to the destination rectangle.
See Also:
Details: This function calculates a scaled copy of a rectangle. The
new rectangle describes an area larger or smaller than the
original, and is centered over or within the original
rectangle's area.
The percent parameter determines the scaling. A value of
100 results in no size change. A value of 200 doubles the
rectangle's area, a value of 50 halves it, a value of 5
yields one twentieth the original size, and so on. The
resulting rectangle's width and height will never be less
than 1.
As an interesting side effect, using a percent value of 0
gives the center point of the source rectangle in the result
rectangle's x/y fields (and 1 in its w/h fields).
Source: aesfuncs\rcscale.c
======================================================================
GemFast v1.8 Page 104
void rc_union(GRECT *sourcerect, GRECT *destrect)
______________________________________________________________________
Summary: Computes a single rectangle that encompasses the area of
both the original rectangles.
Input: The sourcerect parameter is a pointer to the source
rectangle.
The destrect parameter is a pointer to the destination
rectangle. The destination rectangle is used for input and
output.
Returns: Nothing.
See Also:
Details: This function calculates the single large rectangle that
encompasses all the area of both rectangles.
This function does NOT clip to the physical screen
automatically. Negative values in the returned x and y
coordinates are possible if negative values existed in the
inputs.
Source: aesfuncs\rcunion.c
======================================================================
GemFast v1.8 Page 105
VRECT * rc_vadjust(VRECT *prect, short hadjust, short vadjust)
______________________________________________________________________
Summary: Adjust the size of a VRECT rectangle.
Input: The prect parameter is a pointer to the rectangle to be
adjusted.
The hadjust parameter is the number of pixels to adjust by
in the horizontal direction. Positive values enlarge the
rectangle; negative values shrink it.
The vadjust parameter is the number of pixels to adjust by
in the vertical direction. Positive values enlarge the
rectangle; negative values shrink it.
Returns: The pointer to the rectangle.
See Also: rc_gadjust()
Details: This function makes a VRECT rectangle describe a larger or
smaller area. The rectangle remains centered on its
original location, and grows or shrinks equally on each side
in the adjusted dimension(s).
The x/y locations are never allowed to go negative (they are
clipped to zero). The w/h sizes are never allowed to fall
below 1.
Source: aesfuncs\rcadjust.c
======================================================================
GemFast v1.8 Page 106
GRECT * rc_vtog(VRECT *pvrect, GRECT *pgrect)
______________________________________________________________________
Summary: Convert a VRECT rectangle to a GRECT rectangle.
WARNING: There was a major change in this function's behavior in v1.8
that will affect existing code; details below.
Input: The pvrect parameter is a pointer to the source VRECT.
The pgrect parameter is a pointer to the destination GRECT.
Returns: The pointer to the destination GRECT.
See Also: rc_gtov()
Details: The source VRECT is converted to the equivalent GRECT. Do
NOT specify the same rectangle for source and destination.
A VRECT describes an area by the x and y coordinates of
diagonally opposite corners. A GRECT describes an area by
x, y, width and height. This function translates a VRECT to
a GRECT as follows:
pgrect->g_x = pvrect->v_x1;
pgrect->g_y = pvrect->v_y1;
pgrect->g_w = pvrect->v_x1 - pvrect->g_x2 + 1;
pgrect->g_h = pvrect->v_y1 - pvrect->g_y2 + 1;
GemFast versions prior to v1.8 did not apply the +1
correction to the second pair of coordinates. This was just
plain wrong, and it had to be fixed even though you may now
have to go remove some +1 expressions in your existing code
where you were compensating for the broken behavior of the
old versions. ::sigh:: Sorry.
Source: aesfuncs\rcgtov.c
======================================================================
GemFast v1.8 Page 107
MACRO RECTARRAY(GRECT *prect [or] VRECT *prect)
______________________________________________________________________
Summary: Pass the rectangle pointer as a short * type.
Input: The prect parameter is a pointer to a GRECT or VRECT.
Returns: N/A
See Also: RECTVALS() RECTPTRS()
Details: This macro simply recasts the provided pointer to a short *
pointer. It is useful primarily for passing a VRECT to a
VDI function that expects a pointer to an array of xy
coordinates.
The macro is defined as:
#define RECTARRAY(r) ((short *)(r))
Example: To draw a filled box that is described by a given GRECT, you
could use the following code:
GRECT *objrect;
VRECT boxrect;
rc_gtov(objrect, &boxrect); // convert to VDI coords
v_bar(vhandle, 2, RECTARRAY(&boxrect));
This sort of conversion is only necessary when the host
compiler supports prototypes. Using this macro instead of
just passing &boxrect directly will make your code portable
to compilers that enforce pointer checking via prototypes.
Source: GEMFAST.H
======================================================================
GemFast v1.8 Page 108
MACRO RECTPTRS(GRECT *prect)
______________________________________________________________________
Summary: Pass pointers to each of the rectangle's fields.
Input: The prect parameter is a pointer to a GRECT.
Returns: N/A
See Also: RECTVALS() RECTARRAY()
Details: This macro expands to a set of four pointers to the four
fields of the GRECT structure. It provides a shorthand
notation for GEM functions which return xywh values via
pointers you provide in the call.
The macro is defined as:
#define RECTPTRS(r) &((r)->g_x), &((r)->g_y), \
&((r)->g_w), &((r)->g_h)
Example: To obtain the current coordinates of a window, use:
GRECT wrect;
wind_get(whandle, WF_CURRXYWH, RECTPTRS(&wrect));
This is equivalent to coding:
wind_get(whandle, WF_CURRXYWH,
&wrect.g_x, &wrect.g_y, &wrect.g_w, &wrect.g_h);
It also works with pointers to GRECTs as follows:
GRECT *wrect;
wind_get(whandle, WF_CURRXYWH, RECTPTRS(wrect));
Source: GEMFAST.H
======================================================================
GemFast v1.8 Page 109
MACRO RECTVALS(GRECT *prect)
______________________________________________________________________
Summary: Pass the values of each of the rectangle's fields.
Input: The prect parameter is a pointer to a GRECT.
Returns: N/A
See Also: RECTPTRS() RECTARRAY()
Details: This macro expands to a set of four values from the four
fields of the GRECT structure. It provides a shorthand
notation for GEM functions which accept xywh values as four
discreet parameters.
The macro is defined as:
#define RECTVALS(r) (r)->g_x, (r)->g_y, \
(r)->g_w, (r)->g_h
Example: To set the current coordinates of a window, use:
GRECT wrect;
// put some values into wrect somehow
wind_set(whandle, WF_CURRXYWH, RECTVALS(&wrect));
This is equivalent to coding:
wind_set(whandle, WF_CURRXYWH,
wrect.g_x, wrect.g_y, wrect.g_w, wrect.g_h);
It also works with pointers to GRECTs as follows:
GRECT *wrect;
wind_set(whandle, WF_CURRXYWH, RECTVALS(wrect));
Source: GEMFAST.H
======================================================================
GemFast v1.8 Page 110
void wc_scroll_calc(short curline, short datalines, short windowlines
short *pslidesize, short *pslidepos)
______________________________________________________________________
Summary: Calculate the slider size and position for a window.
Input: The curline parameter is a value between 0 and datalines
which is the current line at the top of the window.
The datalines parameter is the number of lines of data
available to be displayed.
The windowlines parameter is the number of lines the window
can display at its current size.
The pslidesize parameter is a pointer to a short into which
the slider size will be returned. The returned value will
be in the range of -1 <= value <= 1000, where -1 indicates
(to GEM, via a wind_set() call) that the system-defined
minimum size should be used.
The pslidpos parameter is a pointer to a short into which
the slider position will be returned. The returned value
will be in the range of 1 <= value <= 1000.
Returns: Nothing.
See Also:
Details: This function assists you in calculating window slider size
and position values appropriate for use in a wind_set()
call. It automatically enforces a reasonable minimum value
for the slider size.
While the parameter names seem to indicate that this
function works on the basis of lines of text, these values
are really expressed in arbitrary units. A 'line' is one
quantum of information that can be displayed in a window.
For graphics work, it may represent a band of image that's
10 pixels high or wide, for example.
Source: aesfuncs\wcscrcal.c
======================================================================
GemFast v1.8 Page 111
Resource Library
The resource library contains functions which manipulate an
entire object tree, or a list of objects in a tree. It
includes functions that simplify access to the strings in
your dialogs, functions that alter the appearance of the
buttons in a dialog, and a few miscellaneous things.
======================================================================
GemFast v1.8 Page 112
short rsc_cubuttons(OBJECT *ptree)
______________________________________________________________________
Summary: Change all buttons in a dialog tree to CUA-style buttons.
Input: The ptree parameter is a pointer to the dialog tree to be
modified.
Returns: Zero for success, or a negative (TOS) error code.
See Also: rsc_rrbuttons()
Details: This function modifies the visual appearance of all non-exit
buttons in a dialog, transforming them to passive G_USERDEF
objects and supplying a custom drawing function. The visual
style of selection (on/off) and radio buttons is similar to
the CUA standard used by Windows 3 and other systems. Exit
buttons aren't changed, because GEM exit buttons are
already CUA-ish.
This function lets you use a standard GEM resource editor to
create dialogs using GEM buttons. The only restriction on
resource design is that your buttons' boxes should be at
least 3 characters wider than the strings they contain. A
CUA-style selection or radio button includes a graphic box
and whitespace equal to 3 character widths in front of the
displayed button string.
This function allocates a block of memory to contain the
XUSERBLK structures that it attaches to the button objects.
If the allocation fails, ENSMEM (-39) is returned. It is
also possible to get a return value of -35 (no more handles)
if the VDI shared workstation can't be opened.
Each selection or radio button object in the dialog tree is
transformed into an extended G_USERDEF object. The main
implication of this transformation is that the button's
string pointer is moved from the object's ob_spec field to
the XUSERBLK ob_spec field. If you use obj_gstring(),
obj_sstring(), rsc_gstrings(), and/or rsc_sstrings() instead
of directly accessing the object's ob_spec field, you don't
have to worry about this at all.
Other than the button string pointer, you can continue to
access the buttons in the usual way, directly accessing the
ob_flags and ob_state fields as needed. In addition, you
can use the extended object type as you wish; this function
changes the lower 8 bits of the ob_type field to G_USERDEF,
but leaves the upper 8 bits alone.
Source: aesfuncs\rsccubtn.c
======================================================================
GemFast v1.8 Page 113
void rsc_gstrings(OBJECT *ptree, int object, char **ppstr, ...)
______________________________________________________________________
Summary: Get the string pointers for one or more string-related
objects in a dialog tree.
Input: The ptree parameter is a pointer to the dialog tree
containing the string-related objects.
The object parameter is the index of the first object for
which you want to retrieve the string pointer.
The ppstr parameter is a pointer to your variable
(char* type). The string pointer for the object is stored
here.
The ... parameters are additional object/ppstr pairs. Use
an object number of -1 to indicate the end of the list.
Returns: Nothing.
See Also: rsc_sstrings() obj_ppstring()
Details: This allows you to easily initialize your local string
pointers to point at string-related objects in a dialog
tree. The description of the obj_ppstring() function
contains details on what objects are string-related.
You must specify at least one object/ppstr pair following
the tree pointer in the call. You can specify any number of
pairs following the first one to retrieve the pointers for
more than one object with a single call. Specify -1 for the
index following the last pair. (There's no need to supply a
pointer to go with the -1 object index.)
This function understands how to find the real string
pointer for each of string-related object type. It copes
with the INDIRECT flag. It understands extended G_USERDEF
objects, where ob_spec has been moved into the XUSERBLK.
This function gives you pointers which point into the
resource data area. If you modify the strings using these
pointers, please remember that your resource editor has only
allocated enough space in the resource data to hold the
strings as you typed them when you built the object. In
other words, you can define a button as "OK", and then at
runtime use this function to get a pointer to the button
text. But, if you do something like
strcpy(buttonptr, "Not Okay");
then you end up corrupting the resource data, because you
copied an 8-character string into a space only 2 characters
wide.
You can avoid this modify-in-place problem by defining your
======================================================================
GemFast v1.8 Page 114
strings big enough in the resource editor, or by using
rsc_sstrings() to make the objects point to strings
allocated within your program rather than working with the
strings directly in the resource data area. In this case,
you can define dummy strings (I use "x") in the resource
editor to avoid wasting space, since the strings you define
are not used at runtime anyway after you use rsc_sstrings()
to point objects at your program-defined strings.
Example: To retrieve the string pointers for a button and a text
object, use code such as the following:
char *editstring;
char *btnstring;
void dial_init()
{
rsc_gstrings(mydialog,
EDITOBJ, &editstring,
BUTTON1, &btnstring,
-1);
*editstring = 0; // empty the edit string
strcpy(btnstring, " Go "); // set the button text
}
Source: aesfuncs\rscgstr.c
======================================================================
GemFast v1.8 Page 115
void rsc_gtrees(int treeindex, OBJECT **pptree, ...)
______________________________________________________________________
Summary: Retrieve the pointers to one or more dialog trees within the
resource data area.
Input: The treeindex parameter is the index of the tree. This is
the name you assigned the tree in the resource editor.
The pptree parameter is a pointer to your tree pointer
variable (OBJECT * type).
The ... parameters are additional treeindex/pptree pairs.
Use an index value of -1 to indicate the end of the
parameter list.
Returns: Nothing.
See Also:
Details: This function simplifies the process of getting your
resource tree pointers. Typically, your program contains an
init routine which has a series of rsrc_gaddr() calls. This
function allows you to replace that series of calls with a
single call.
Example: If your resource data contains 3 trees, you might use:
OBJECT *menu;
OBJECT *maindialog;
OBJECT *selectdialog;
prg_init()
{
appl_init();
if (!rsrc_load("myrsc.rsc")) {
// complain and die
}
rsc_gtrees(MENUTREE, &menu,
MAINTREE, &maindialog,
SELCTONE, &selectdialog,
-1);
menu_bar(menu, TRUE);
// etc
}
Source: aesfuncs\rscgtree.c
======================================================================
GemFast v1.8 Page 116
short rsc_rrbuttons(OBJECT *ptree)
______________________________________________________________________
Summary: Change all radio buttons in a dialog tree to display as
rounded-corner buttons.
Input: The ptree parameter is a pointer to the dialog tree to be
modified.
Returns: Zero for success, or a negative (TOS) error code.
See Also: rsc_cubuttons()
Details: This function modifies the visual appearance of all radio
buttons in a dialog, transforming them to extended G_USERDEF
objects and supplying a custom drawing function which draws
radio buttons with rounded corners. This gives the user
immediate visual cues as to which buttons are selection
(on/off) buttons and which are radio buttons. The selection
buttons (not modified by this function) will display as
standard square-corner buttons, and radio buttons will have
rounded corners.
This function lets you use a standard GEM resource editor to
create dialogs using GEM buttons. There are no restrictions
on the way you design your buttons.
This function allocates a block of memory to contain the
XUSERBLK structures that it attaches to the button objects.
If the allocation fails, ENSMEM (-39) is returned. It is
also possible to get a return value of -35 (no more handles)
if the VDI shared workstation can't be opened.
Each selection or radio button object in the dialog tree is
transformed into an extended G_USERDEF object. The main
implication of this transformation is that the button's
string pointer is moved from the object's ob_spec field to
the XUSERBLK ob_spec field. If you use rsc_gstrings()
and/or rsc_sstrings() as your sole access to the button's
string, you don't have to worry about this at all.
Other than the button string pointer, you can continue to
access the buttons in the usual way, directly accessing the
ob_flags and ob_state fields as needed. In addition, you
can use the extended object type as you wish; this function
changes the lower 8 bits of the ob_type field to G_USERDEF,
but leaves the upper 8 bits alone.
I would like to recommend that you don't mix button styles
in the same application. Pick one style, (GEM, CUA, or RR)
and use it for all your dialogs.
Source: aesfuncs\rsrrubtn.c
======================================================================
GemFast v1.8 Page 117
void rsc_sstrings(OBJECT *ptree, int object, char *pstr, ...)
______________________________________________________________________
Summary: Set the string pointers for one or more string-related
objects in a dialog tree.
Input: The ptree parameter is a pointer to the dialog tree
containing the string-related objects.
The object parameter is the index of the first object for
which you want to set the string pointer.
The pstr parameter is a pointer to your string variable
(char [] or "" type). This pointer is copied into the
string object's string pointer field (ob_spec, te_ptext,
etc).
The ... parameters are additional object/pstr pairs. Use an
object number of -1 to indicate the end of the list.
Returns: Nothing.
See Also: rsc_gstrings() obj_ppstring()
Details: This allows you to easily initialize string-related objects
in a dialog tree to point at strings defined within your
program. The description of the obj_ppstring() function
contains details on what objects are string-related.
You must specify at least one object/pstr pair following the
tree pointer in the call. You can specify any number of
pairs following the first one to retrieve the pointers for
more than one object with a single call. Specify -1 for the
index following the last pair. (There's no need to supply a
pointer to go with the -1 object index.)
This function understands how to find the real string
pointer for each of string-related object type. It copes
with the INDIRECT flag. It understands extended G_USERDEF
objects, where ob_spec has been moved into the XUSERBLK.
This function attaches string data defined in your program
to string-related objects in your dialog trees. This is
especially handy for editable text objects, because some
resource editors don't allocate enough space for the object
in the resource data. If you define an editable text object
and supply a te_pvalid string that allows 20 chars of input,
but you define an initial string of "abc" for the field,
some resource editors will only allocate 3 bytes of resource
string space for the field. When the user enters 20 chars
of data into the 3-byte field, other resource data gets
corrupted. To avoid this, you can allocate a 20-byte
character array in your program, and use this function to
make the editable field's te_ptext pointer point at your
======================================================================
GemFast v1.8 Page 118
array instead of the 3-byte area in the resource data.
Example: To supply a local string constant for a G_STRING item, a
local character array for an editable item, and the text for
an icon, you might use code like this:
char editbuffer[20] = ""; // 20 bytes, starts empty
char iconname[] = "This is ICON #1"; // a silly name
void dial_init()
{
rsc_sstrings(mydialog,
EDITOBJ, editbuffer,
ICON1, iconname,
TITLESTR, "My dialog v1.1a",
-1);
}
Source: aesfuncs\rscsstr.c
======================================================================
GemFast v1.8 Page 119
void rsc_sxtypes(OBJECT *ptree, int object, int xtype, ...)
______________________________________________________________________
Summary: Sets the extended object type in one or more objects.
Input: The ptree parameter is a pointer to the tree which contains
the objects.
The object parameter is the index of the first object for
which you want to set the extended object type.
The xtype parameter is the extended object type (a value
between 0x00 and 0xFF) to be set in the object.
The ... parameters are additional object/xtype pairs. Use
an object number of -1 to indicate the end of the list.
Returns: Nothing.
See Also: obj_bmbuttons() obj_xtfind()
Details: This function sets the extended object type field in one or
more objects within a tree. Extended object types are
discussed under the obj_bmbuttons() and obj_xtfind()
functions.
Some resource editor programs let you set the extended type
when you create the resource, others don't allow that. Use
this function to set the extended type values during program
startup when you can't set them in the resource editor.
Source: aesfuncs\rscsxtyp.c
======================================================================
GemFast v1.8 Page 120
void rsc_treefix(OBJECT *ptree)
______________________________________________________________________
Summary: Performs xywh fixup on all objects in a tree.
Input: The ptree parameter is a pointer to the tree which needs
resolution fixup.
Returns: Nothing.
See Also:
Details: This function calls rsrc_obfix() for every object in the
tree. It's just a shortcut for calling the GEM object fixup
for all objects in a tree, and does not provide any custom
resolution fixup, scaling, etc.
Use this function to do fixup on resource trees which are
embedded in your source code. Do NOT use this function on
trees loaded via rsrc_load(), since that function
automatically applies resolution fixup as it loads the
resource data.
Source: aesfuncs\rsctrfix.c
======================================================================
GemFast v1.8 Page 121
Window Library
The window library contains functions that work with windows
and window-related events.
======================================================================
GemFast v1.8 Page 122
short wnd_top(void)
______________________________________________________________________
Summary: Obtain the handle of the current top window.
Input: Nothing.
Returns: The handle of the currently-topped window.
See Also:
Details: This function is a shortcut call for wind_get(0,WF_TOP,...),
since querying the current top window handle is something
GEM programs seem to do a lot.
Source: aesutil.s\wndtop.s
aesutil.c\wndtop.c
======================================================================
GemFast v1.8 Page 123
void wind_update(short flag)
void wnd_update(short flag)
______________________________________________________________________
Summary: Set or unset the window or mouse update flag, with stacked
call logic.
NOTE: A macro in GEMFAST.H automatically remaps your wind_update()
calls to wnd_update().
Input: The flag parameter is any of the GEM-defined flags for
wind_update(). (BEG_UPDATE, END_UPDATE, BEG_MCTRL,
END_MCTRL).
Returns: Nothing.
See Also:
Details: This function causes wind_update() calls to be handled like
hide/show mouse calls: 3 BEG_UPDATE calls will require 3
END_UPDATE calls; only the 3rd END_UPDATE actually gets
passed to GEM.
This type of functionality is required in blackbox library
routines (such as GemFast itself), where the library routine
can't know whether wind_update() has already been called by
the application or not. GEM will consider a single
END_UPDATE call sufficient to cancel any number of preceding
BEG_UPDATE calls. That could result in a library routine
accidentally releasing the update flag before the
application was ready for it.
This function keeps separate internal counters for the
UPDATE and MCTRL flags; the counter is incremented on each
BEG_whatever call, and decremented on each END_whatever
call. It only passes a BEG_whatever call through if that
counter is currently at zero. When it sees an END_whatever
call, it decrements the counter, and passes the call through
to GEM only if the counter has dropped back to zero.
A macro in GEMFAST.H automatically routes your exiting
wind_update() calls through wnd_update(). This is required
because all calls must go through this routine for the
stacked BEG/END system to work.
Source: aesfuncs\wndupdat.c
======================================================================
GemFast v1.8 Page 124
Extended Binding Functions
The extended binding functions provide an alternate calling
format for some of the standard GEM functions. For the most
part, the alternate standard allows you to pass a pointer to
a structure in place of the discreet parms accepted by the
corresponding GEM function. This has several advantages,
including smaller faster code at runtime, and easier-to-read
source code.
These functions are all portable to compilers that have
their own (non-GemFast) low-level bindings.
I would like to recommend that you use the envx_multi()
function instead of evnt_multi() in all your programs. Get
used to working with the XMULTI structure it uses. To be
quite frank, it's looking more and more like you'll be
required to use it in GemFast v2.0.
======================================================================
GemFast v1.8 Page 125
short evnx_multi(XMULTI *xm)
______________________________________________________________________
Summary: Call evnt_multi() passing just a single pointer.
Input: The xm parameter is a pointer to an XMULTI structure.
Returns: The mask of events which occurred; xm->mwhich.
Details: This function keeps all the input and output parms for an
evnt_multi() call in a single structure. This is more
efficient than stacking and unstacking 50-some bytes of
parameters on each call, and it also allows you to "pass
off" event handling to a series of event handlers by passing
a single pointer to each handler. GemFast 2.0 will make
heavy use of the latter technique.
The XMULTI structure is defined in GEMFAST.H, as follows:
typedef struct xmulti {
short msgbuf[8]; /* Message buffer
short mflags, /* Mask of events to wait for */
mbclicks, /* Button clicks to wait for */
mbmask, /* Which buttons to wait for */
mbstate, /* Wait for button up/down */
mm1flags; /* M1 event: wait for in/out */
GRECT mm1rect; /* M1 event: coordinates */
short mm2flags; /* M2 event: wait for in/out */
GRECT mm2rect; /* M2 event: coordinates */
long mtcount; /* Timer count (a longword!) */
short mwhich, /* Bitmap of occurred events */
mmox, /* Mouse x at time of event */
mmoy, /* Mouse y at time of event */
mmobutton, /* Mouse buttons at event */
mmokstate, /* Keystate (shift) at event */
mkreturn, /* Key pressed */
mbreturn; /* Mouse button click count */
} XMULTI;
You can use the values in the XMULTI structure just as you
would use discreet variables with an evnt_multi() call.
I would like to caution against a technique I've seen in
some programs: don't compare the return value (or xm.mwhich
field) using the equality operator. This field holds a
bitmap of events that occurred, and GEM *will* return
multiple events at once in some situations. You should test
for each event type you expect using the & operator.
I would like to recommend that you get used to using this
function, because the overwhelming likelihood is that you'll
have to use it in GemFast 2.0 for the library to work right.
Source: gemfuncs\evnxmult.c
======================================================================
GemFast v1.8 Page 126
short frmx_center(OBJECT *ptree, GRECT *prect)
______________________________________________________________________
Summary: Call form_center() passing a single pointer for the return
values.
Input: The ptree parameter is a pointer to the object tree to be
centered.
The prect parameter is a pointer to a GRECT structure into
which the on-screen sizes of the dialog are returned.
Returns: TRUE (1) always.
See Also: frm_sizes()
Details: This function allows you to pass a single pointer to an
output rectangle, instead of the four pointers required by
the standard form_center() function.
Source: gemfuncs\frmxcent.c
======================================================================
GemFast v1.8 Page 127
short frmx_dial(short action, GRECT *little, GRECT *big)
______________________________________________________________________
Summary: Call form_dial() passing pointers to the little and big
rectangles.
Input: The action parameter is the GEM-defined action flag.
The little parameter is a pointer to the small-size
rectangle used with the FMD_GROW and FMD_SHRINK action
flags. Must not be NULL, but may point to a rectangle
containing all zeros.
The big parameter is a pointer to the big-size rectangle;
the rectangle the dialog will occupy on-screen. Must not be
NULL.
Returns: TRUE (1) always.
See Also:
Details: This function allows you to call form_dial() passing just
pointers to the two rectangles instead of passing all eight
rectangle fields as discreet values.
Source: gemfuncs\frmxdial.c
======================================================================
GemFast v1.8 Page 128
short grfx_dragbox(GRECT *startrect, GRECT *boundrect,
GRECT *endrect)
______________________________________________________________________
Summary: Call graf_dragbox() passing just rectangle pointers.
Input: The startrect parameter is a pointer to the starting
location for the dragbox.
The boundrect parameter is a pointer to the rectangle
defining the boundary in which the ending rectangle is
confined.
The endrect parameter is a pointer to the rectangle which
will receive the results after the call. This may point to
the same rectangle as startrect without any problems.
Returns: Non-zero on success, or zero on failure (per GEM).
See Also:
Details: This function allows you to pass rectangle pointers instead
of discrete parameters to graf_dragbox(). In the most
common usage, the startrect and endrect parameters will be
the same, so that the rectangle is 'moved' by the dragbox
operation. The width and height will never be changed by
this function, only the x and y. You can often use the
global desktop rectangle variable (&gl_rwdesk) as the
boundrect parameter.
Source: gemfuncs\grfxdrag.c
======================================================================
GemFast v1.8 Page 129
short winx_calc(short type, short kind, GRECT inrect, GRECT *outrect)
______________________________________________________________________
Summary: Call wind_calc() passing a single pointer to the output.
Input: The type, kind, and inrect parameters are identical to the
corresponding wind_calc() parameters.
The outrect parameter is a pointer to the output rectangle
where the results of the calculation are stored.
Returns: Zero on error, or non-zero on success.
See Also:
Details: Please note that the inrect parameter is a structure passed
by value (4 values stacked) not a pointer to a rectangle.
Source: gemfuncs\winxcalc.c
======================================================================
GemFast v1.8 Page 130
short winx_get(short whandle, short field, GRECT *outrect)
______________________________________________________________________
Summary: Call wind_get() passing a single output pointer.
Input: The whandle and field parameters are identical to the
corresponding wind_get() parameters.
The outrect parameter is a pointer to the output rectangle
where the results of the query are stored.
Returns: Zero on error or non-zero on success.
See Also:
Details: Please note that this function will always write 8 bytes of
output to the memory location indicated by outrect even if
the type of query you're doing normally returns less
information that. (IE, don't use &integer_variable for this
parameter, or the memory following the integer variable will
be overwritten as well.)
Source: gemfuncs\winxget.c
======================================================================
GemFast v1.8 Page 131
Extended VDI Functions
The extended VDI functions provide several functions not
documented in standard VDI reference manuals.
======================================================================
GemFast v1.8 Page 132
short vdicall(short *control, short *intin, short *ptsin,
short *intout, short *ptsout)
______________________________________________________________________
Summary: Direct call to VDI with caller-specified structures/arrays.
Input: All input parameters are pointers to arrays of int. See
your VDI documentation for details on each of the arrays.
Returns: The contents of intout[0].
Details: This function allows you to call VDI functions not directly
supported by the VDIFAST.A library. Within your program,
you set up arrays containing the parameters for the
function, and then pass pointers to those arrays to this
routine. It will combine the pointers into a VDI parameter
block, and issue the VDI trap.
You must always supply a non-NULL pointer for control, and
the values in control must contain everything VDI needs to
process the call. (IE, opcode, sub-opcode if needed, intin
count, ptsin count, and extended control info such as the
FDB pointers for a blit, if needed.) You never need to
supply the intout or ptsout count values in the control
array; VDI will fill those in (and will ignore anything you
put there anyway).
The other array pointers may be NULL if they are not needed
for a given VDI call. (If there are no ptsin parms for the
call, just code NULL for the ptsin parameter.) The intout
array is handled specially: if you supply a NULL intout
pointer, the vdicall() routine allocates a 256-byte intout
array on the stack for you. It returns the value from
intout[0] as the function return value, and discards the
rest of the array. This is mainly to provide ease-of-use in
coding custom bindings which only need a single-word return
value.
Source: vdibind\vdicall.s
======================================================================
GemFast v1.8 Page 133
long vgd_detect(void)
long vg_gdos(void)
______________________________________________________________________
Summary: Detect presence of GDOS on system.
Input: None.
Returns: One of the following:
GDOS_NONE - GDOS is not available.
GDOS_FNT - 'Font GDOS' is available.
GDOS_FSM - 'FSM' or 'Speedo' GDOS is available.
Details: The constants are defined in GEMFBIND.H or your compiler's
bindings header file. The GDOS_NONE value is equal to zero.
Source: vdibind\vgdetect.s
======================================================================
GemFast v1.8 Page 134
void v_gchar(short vdi_handle, short x, short y, char outchar)
______________________________________________________________________
Summary: Output a single character.
Input: The vdi_handle parameter is the handle of the VDI
workstation.
The x and y parameters are the coordinates at which the
character is placed.
The outchar parameter is the character to output.
Returns: Nothing.
Details: This function writes a single character to the screen. It
requires less setup than the standard v_gtext() function,
and is a bit faster and easier to use.
This function is only available in the HSC and GNU versions
of GemFast.
Source: vdibind\vgchar.s
======================================================================
GemFast v1.8 Page 135
Extended Object Library
The extended object library contains functions which
implement a set of new 'extended' objects, in effect
creating new types of objects not directly defined by GEM.
It also contains functions for working with the new types of
objects (eg, setting or querying their current value.)
Background
GEM defines a small variety of standard object types, such
as buttons, strings, text edit fields, boxes, etc. GEM
programmers have long been creating dialog boxes that
contain related aggregates of these basic objects which work
together to give the appearance of a more complex object.
The system file selector is a good example of this: a
collection of boxes, boxchars, and text objects work
together to give the appearance of a scrolling window within
the dialog box.
The only problem with the existing techniques is that
they're difficult to implement. Every dialog that contains
one of these complex aggregate objects requires a custom
dialog handler function. Coding just one such function can
take a week or more, and all that effort often leaves you
with an application-specific implementation of a single
dialog box which would then require even more work to use it
in other applications.
GemFast now supports a variety of pre-written extended
objects that you can easily use in your applications. There
are two types of extended objects: passive and active.
Passive objects just give a different visual appearance to a
standard GEM object, or define a new type of display-only
object, but there is no special action associated with
clicking on or otherwise manipulating the object. They are
implemented with a standard G_USERDEF drawing routine, and
the standard GEM form_do() handler or any replacement dialog
handler can work with these objects.
Active objects are like mini-dialogs embedded within a
dialog. They often consist of multiple objects working
together, but logically they take just one object slot in
your dialog tree. These objects react to a mouse click on
their various components by using an object-specific custom
dialog handler invoked by frm_dialog(). For this reason,
the normal system form_do() handler and compatible
replacment handlers cannot be used with dialogs containing
active extended objects. (The objects would be drawn
correctly, but would fail to behave properly without
frm_dialog() dispatching the custom handlers attached to the
object.)
======================================================================
GemFast v1.8 Page 136
Using Extended Objects
Using extended objects is fairly simple. A resource
construction program won't know anything about extended
objects, so when designing your dialog, G_BOX objects serve
as placeholders for the extended objects. The G_BOX
objects define the size and location of the extended object,
and effectively reserve a slot in the object tree array for
the extended object. During program initialization, you
call a GemFast extended object library function to transform
the placeholder box into the desired type of extended
object.
Some extended objects impose minimum and maximum sizes for
the placeholder G_BOX object you design into your dialogs.
These limits are documented in the create() function for
each object, and are expressed in terms of characters. If
the routine lists the limit as None, that means that the
actual limit is the screen resolution. The library routines
are resolution-independent, and fractional character
placements and sizes work fine. (EG, if the minimum height
is 1 character for an object, you can design the dialog with
a placeholder box that is 1 character plus 4 pixels high,
but the usual problems of scaling objects at rsrc_load()
time will still occur, just as they would if the G_BOX
object wasn't transformed into an extended object.)
Once the transformation has been done, you just call
frm_dialog() as usual to process the dialog. If the
extended object is an active type, frm_dialog() and the
extended object library functions work together to manage
interaction between the object and the user. Control
doesn't return to your code until the user clicks on an exit
button in your dialog box. (In some cases, a double-click
on a component within an extended object is equivalent to
clicking on the dialog's default exit button. This is
analogous to double-clicking a file in the system file
selector: the double-click is the same as a single-click on
a filename followed by a click on the default OK button.)
Most extended objects have a value associated with them.
For example, the numeric slider object represents a numeric
value; the text scroll list object has a currently-selected
string within the list, and so on. The object library
functions obj_gvalue(), obj_svalue(), obj_gstring(), and
obj_string() can be used to get and set the values
associated with an extended object, just as they would be
used in getting/setting the values of standard GEM objects.
In some cases, there are multiple values associated with an
extended object. For example, in a text scroll list object
there is the currently-selected string, the index of the
string currently at the top of the visible list, the number
======================================================================
GemFast v1.8 Page 137
of strings in the list, and so on. In this case, the
extended object library provides functions to get and set
these related values, which are usually stored in hidden
data structures attached to the object.
If you look at the GemFast source code, you'll notice that
some extended object types have custom data structures
attached to them through the object ob_spec pointer.
Sometimes these objects are a standard XUSERBLK structure,
sometimes they're custom structures that have an XUSERBLK as
the first field. You must never access these structures
directly or make any assumptions about what they contain.
If you do so, your programs will break with future releases
that have new library internals. Use only the functions
defined in this document to access extended objects.
======================================================================
GemFast v1.8 Page 138
void xob_nslide_change(OBJECT *tree, short object,
long newmin, long newmax)
______________________________________________________________________
Summary: Changes the range of numbers a numeric slider can represent.
Input: The ptree parameter is a pointer to the object tree
containing the G_NSLIDE object.
The object parameter is the index of the G_NSLIDE object.
The newmin parameter is the smallest number the slider can
be set to.
The newmax parameter is the largest number the slider can be
set to.
Returns: Nothing.
See Also: xob_nslide_create() xob_nslide_get() xob_nslide_set()
Details: This function changes the range of numbers that the numeric
slider can be set to. If the current value of the slider is
outside the new range, the value is clipped to either newmin
or newmax as appropriate. This function does not update the
numeric slider on the screen.
Source: aesfuncs\xobnslid.c
======================================================================
GemFast v1.8 Page 139
short xob_nslide_create(OBJECT *tree, short object,
long min, long max)
______________________________________________________________________
Summary: Creates a G_NSLIDE numeric slider data entry object.
Input: The ptree parameter is a pointer to the object tree
containing the object to be transformed.
The object parameter is the index of the object to be
transformed.
The min parameter is the smallest number the slider can be
set to.
The max parameter is the largest number the slider can be
set to.
Returns: Zero for success or a negative error code.
See Also: xob_nslide_change() xob_nslide_get() xob_nslide_set()
Details: A G_NSLIDE is an active extended object. It is used for
numeric input without requiring the user to type a number.
Visually, the object resembles a window horizontal scroll
control, except that the sliding part of the scroller also
displays the current numeric value.
The user can change the numeric value by clicking on the
left and right arrows to increment/decrement the current
value by one, or by clicking anywhere in the scroll area to
jump the scroller to that location, or by dragging the
scroller to the appropriate location in the scroll area.
The numeric display in the scroller is constantly updated as
the user clicks or drags with the mouse.
The numeric slider occupies exactly the same location on-
screen as the G_BOX placeholder object would. Size limits:
Minimum width: 5 characters
Maximum width: None
Minimum height: 1 character
Maximum height: None (recommended max is 2 characters)
A wider object gives the user better control over the values
that result from dragging the slide bar, especially when the
range of possible values is large.
The xob_nslide_set() function can be used to set the current
value of the numeric slider without user interaction, and to
set the initial value after creating it. By default, the
initial value is zero, or the min or max value if zero is
not within that range.
======================================================================
GemFast v1.8 Page 140
The xob_nslide_get() function can be used to get the current
value of the numeric slider. The standard obj_gvalue() can
also be used to get the current value.
The xob_nslide_change() function can used to change the min
and/or max range limits after the object has been created.
Source: aesfuncs\xobnslid.c
======================================================================
GemFast v1.8 Page 141
long xob_nslide_get(OBJECT *tree, short object)
______________________________________________________________________
Summary: Obtains the current value from a numeric slider object.
Input: The ptree parameter is a pointer to the object tree
containing the G_NSLIDE object.
The object parameter is the index of the G_NSLIDE object.
Returns: The current value displayed in the object.
See Also: xob_nslide_create() xob_nslide_change() xob_nslide_set()
Details: This function obtains the current value being represented by
the numeric slider object. The obj_gvalue() function can
also obtain a numeric slider's value.
Source: aesfuncs\xobnslid.c
======================================================================
GemFast v1.8 Page 142
void xob_nslide_set(OBJECT *tree, short object, long newvalue)
______________________________________________________________________
Summary: Sets a new value in a numeric slider object.
Input: The ptree parameter is a pointer to the object tree
containing the G_NSLIDE object.
The object parameter is the index of the G_NSLIDE object.
The newvalue parameter is the new numeric value for the
object.
Returns: Nothing.
See Also: xob_nslide_create() xob_nslide_change() xob_nslide_get()
Details: This function sets a numeric slider object to a new value.
It does not update the object on-screen. The new value is
clipped to the range previously set for the object. The
obj_svalue() function can also be used to set a new value,
but it would not perform the range enforcement clipping that
this function does; use obj_svalue() with care.
Source: aesfuncs\xobnslid.c
======================================================================
GemFast v1.8 Page 143
short xob_thermo_change(OBJECT *ptree, short object, short increments)
______________________________________________________________________
Summary: Changes the number of increments allotted to a G_THERMO.
Input: The ptree parameter is a pointer to the object tree
containing the G_THERMO object.
The object parameter is the index of the G_THERMO object.
The increments parameter is the number of increments or
'ticks' the thermometer will display.
Returns: Zero on success, or a negative error code.
See Also: xob_thermo_update() xob_thermo_create()
Details: This function changes the number increments a G_THERMO
object can display. It also resets the current increment
count to zero. It does not redraw the object.
Note that the object may change size as a result of this
call, but it will not exceed the dimensions of the original
object before it was transformed into a G_THERMO object.
(See the description of xob_thermo_create() for details on
how the number of increments affects the size and position
of the resulting object on-screen.)
Source: aesfuncs\xobtherm.c
======================================================================
GemFast v1.8 Page 144
short xob_thermo_create(OBJECT *ptree, short object, short increments)
______________________________________________________________________
Summary: Creates a G_THERMO progress display object.
Input: The ptree parameter is a pointer to the object tree
containing the object to be transformed.
The object parameter is the index of the G_BOX object to be
transformed.
The increments parameter is the number of increments or
'ticks' the thermometer will display.
Returns: Zero on success, or a negative error code.
See Also: xob_thermo_update() xob_thermo_change() frm_progress()
Details: A G_THERMO is a passive extended object. The object is used
to indicate progress by incrementally filling the object
interior as progress is made. The interior of the object is
always filled from left to right as progress increments are
made. There is no way to implement vertical or right to
left progress.
Use xob_thermo_update() to increment the filled portion of
the object and optionally update the object on-screen. Use
xob_thermo_change() to change the number of increments the
object can display after it has been created.
The G_THERMO object appears on-screen based on the size and
location of the G_BOX placeholder object, but it may not
occupy all the space of the original object, as described
below. The fill pattern in your original G_BOX object is
used as the fill pattern for the G_THERMO. You cannot
change the fill pattern once the object is transformed.
Size limits:
Minimum width: increments pixels
Maximum width: None
Minimum height: 1 character
Maximum height: None (recommended max is 2 characters)
The increments parameter indicates how many increments the
thermo bar is capable of. Based on the increments, the
G_THERMO object is sized in the horizontal dimension and
centered it within its original horizontal location. The
resizing ensures that the total width is a multiple of the
number of increments that you requested. For example, if
your original G_BOX was 210 pixels wide, and you request 100
increments in the G_THERMO, then the object will be 200
pixels wide, and each time you increment the progress
display, it will add 2 pixels of shading to the interior.
Because the actual object is 10 pixels smaller than the
======================================================================
GemFast v1.8 Page 145
original box, it is displayed at an X offset 5 pixels to the
right of the original object (ie, centered within the space
the original object occupied).
Do not specify more increments than the width of the
original G_BOX object; it would result in an increment width
of zero pixels per tick. If you do so, this function
returns -64 (range error), and doesn't transform the object.
See the xob_thermo_update() function for an example of using
xob_thermo_create().
Source: aesfuncs\xobtherm.c
======================================================================
GemFast v1.8 Page 146
short xob_thermo_update(OBJECT *ptree, short object, short increments,
GRECT *pcliprect)
______________________________________________________________________
Summary: Update the increment count on a G_THERMO object, with
optional redraw.
Input: The ptree parameter is a pointer to the tree.
The object parameter is the index of the G_THERMO object.
The increments parameter is the new increment count for the
object, or one of the following special values:
OBJ_TINCREMENT - Add one to the current increment count.
OBJ_TINQUIRE - Return current increment count without
changing it.
The pcliprect parameter, if non-NULL, specifies the clipping
rectangle for the redraw. If NULL, no redraw is done. If
you need no clipping but want a redraw, pass &gl_rwdesk.
Returns: The increment count that was current before the call.
See Also: xob_thermo_create()
Details: This function updates the increment count on a G_THERMO
object, and optionally redraws the object using the new
count.
If increments is zero or greater, the G_THERMO increment
count is set to increments. If it is OBJ_TINCREMENT, this
function adds one to the current count. The increment count
is clipped to the maximum number of increments set when the
G_THERMO was created or modified by xob_thermo_create().
In general, the OBJ_TINCREMENT (increment by one tick) value
should be the most common value passed for increments.
Another useful technique is to create the G_THERMO with 100
increments and pass successive increments values that
represent current percentage of completion of the task.
If you pass a NULL pointer for a clipping rectangle, the
G_THERMO increment count is updated internally, but the
object is not updated on the screen. This can be handy for
zeroing the increment count before displaying the dialog.
======================================================================
GemFast v1.8 Page 147
Example: To report progress (using your own custom dialog box) as you
do something to each track of a floppy disk, you might use
code such as the following:
OBJECT *pdialog;
rsc_gtrees(PROGRESS, &pdialog, -1);
if (!xob_thermo_create(pdialog, THERMOBAR, numtracks))
complain_and_die();
frm_dial(FRM_DSTART|FRM_DDRAW, pdialog, 0);
for (i = 0; i < numtracks; ++i) {
do_something_to_disk_track(i);
xob_thermo_update(pdialog, THERMOBAR,
OBJ_TINCREMENT, &gl_rwdesk);
}
frm_dialog(FRM_DFINISH, pdialog, 0);
Source: aesfuncs\xobtherm.c
======================================================================
GemFast v1.8 Page 148
short xob_tscroll_create(OBJECT *ptree, short object, short statusobj)
______________________________________________________________________
Summary: Transform an object into a G_TSCROLL text list object.
Input: The ptree parameter is a pointer to the tree.
The object parameter is the index of the object to be
transformed.
The statusobj parameter is the index of another string-
related object in the same tree which reflects the current
selection in text scroll list.
Returns: Zero for success, or a negative error code.
See Also: xob_tscroll_set() xob_tscroll_get()
Details: A G_TSCROLL is an active extended object. It presents a
list of strings in a scrollable text 'window' object, and
allows the user to scroll through the list and/or select one
of the strings.
The currently-selected string appears in reverse video, just
as a SELECTED object would appear in a dialog. In addition,
if a status object is specified at creation time, the
currently selected string is updated into the status object
whenever the user makes a selection from the scrolling list
of strings. The status object can be any string-related
object, including G_STRING, G_TEXT, G_BOXTEXT, etc.
The G_TSCROLL object occupies exactly the same screen area
as the original G_BOX placeholder object. Size limits:
Minimum width: 10 characters
Maximum width: None
Minimum height: 7 characters
Maximum height: 18 characters
The string data occupies only a portion of the G_TSCROLL
object; whitespace gutters and the scroll controls occupy
the remaining space. The scroll controls and whitespace
occupy five character widths horizontally, and whitespace
occupies 2 character heights vertically. Thus, you must
size the G_BOX placeholder object 5 characters wider than
the width of the strings you want to display, and 2
characters higher than the number of lines you want to
display. If any of the displayed strings are wider than the
data area of the G_TSCROLL object, they are automatically
clipped to the data area.
Zero or more strings can be displayed with the G_TSCROLL
object. If there are more strings than there are lines
available in the data window, the user can scroll through
======================================================================
GemFast v1.8 Page 149
the list of strings using what appear to be standard window
scroll controls. The scrolling differs from a standard
window, however, in that the list scrolls as the slider bar
is dragged.
If the user clicks on a string in the data area, that string
becomes the currently-selected item. If the user double-
clicks on a string in the data area, that string becomes the
currently-selected item, and the frm_dialog() function
driving the user interaction returns the index of the
dialog's default exit button. For this reason, the 'Okay'
or other positive-action exit button for the dialog should
always be marked as the default exit object. (If the dialog
doesn't have a default exit button, a double-click on a
string is the same as a single-click.)
The obj_gstring() function will return a pointer to the
currently-selected string within a G_TSCROLL object. The
xob_tscroll_get() function returns the pointer, as well as
the index of the currently-selected string, and the index of
the string currently at the top of the data window. If no
string is currently-selected, a NULL pointer is returned for
the string pointer, and NO_OBJECT is returned for the index.
The xob_tscroll_set() function is used to attach the list of
strings to the object, and to set other parameters that
affect the object. Until a list of strings is attached to
the object, the data window appears empty. The list of
strings is in the form of an array of pointers to the
strings; this is detailed under xob_tscroll_set().
Source: aesfuncs\xobtscro.c
======================================================================
GemFast v1.8 Page 150
short xob_tscroll_get(OBJECT *ptree, short object, char **curstring,
short *curindex, short *topindex)
______________________________________________________________________
Summary: Obtains information about the state of a G_TSCROLL object.
Input: The ptree parameter is a pointer to the tree.
The object parameter is the index of the object to be
transformed.
The curstring parameter, if non-NULL, is used to return a
pointer to the currently-selected string.
The curindex parameter, if non-NULL, is used to return the
index of the currently-selected string.
The topindex parameter, if non-NULL, is used to return the
index of the line currently shown at the top of the window.
Returns: The index of the currently-selected string, or NO_OBJECT if
no string is selected.
See Also: xob_tscroll_create() xob_tscroll_set() obj_gstring()
Details: This function returns information about the current state of
a G_TSCROLL object. If you need only a pointer to the
currently-selected string, use obj_gstring().
If no string is currently selected, NO_OBJECT is returned
into *curindex and as the return value of the function, and
a NULL pointer is returned into *curstring.
Any or all of the returned-value pointers can be NULL to
indicate that you don't want that item of information.
Source: aesfuncs\xobtscro.c
======================================================================
GemFast v1.8 Page 151
void xob_tscroll_set(OBJECT *ptree, short object, char **datalist,
short numlines, short curindex, short topindex)
______________________________________________________________________
Summary: Sets new values into a G_TSCROLL object.
Input: The ptree parameter is a pointer to the tree.
The object parameter is the index of the object to be
transformed.
The datalist parameter is a pointer to an array of string
pointers; the list of strings displayed by the object.
The numlines parameter is the number of lines in the string
list.
The curindex parameter is the index of the string which is
to be considered currently-selected.
The topindex parameter is the index of the string which is
to appear as the top line in the data window.
Returns: Nothing.
See Also: xob_tscroll_create() xob_tscroll_get()
Details: This function changes the state of a G_TSCROLL object. Use
it to attach a list of strings to an object, or to change
the state of the list currently attached to the object.
This function does not update the object on-screen. If a
change is made to the currently-selected item, and a status
object was associated with the G_TSCROLL at creation time,
the new selected string pointer is set into the status
object, but the status object is not updated on-screen.
The list of strings has the form of an array of pointers to
the strings. If the last pointer in the array is NULL, you
can pass -1 for the numlines parameter, and this function
will count the number of strings internally. If the last
pointer in the array is not NULL, you must pass a positive
value for numlines when you attach a new string list.
The parameters interact with each other depending on the
values you pass, as described below. Despite the arcane
interactions possible between the parameters, the most
common use of this function is to attach an initial or new
list of strings. In this context, usage is fairly simple;
pass a non-NULL datalist pointer, and -1 for all the other
parameters. This attaches the list, automatically counts
the lines in the list, sets the data window to display the
first list line at the top of the window, and starts with no
string initially selected. If the dialog containing the
list is used multiple times after doing this, and the
======================================================================
GemFast v1.8 Page 152
contents of the list haven't been changed by other actions
of your program, the user will always see the list in the
same state as the last time it was visible. If something
done by your program does cause the list contents to change
between calls, just use the datalist, -1, -1, -1 sequence
again to attach the new list (or make the object see the
changes in the existing list).
If the datalist parameter is NULL, the existing list of
strings remains attached to the object. If non-NULL, a new
list of strings is attached to the object. If curindex is
not also specified, no string from the new list is
considered currently-selected. If the topindex parameter is
not also specified, the first line of the new list is
displayed at the top of the data window.
The numlines parameter is the number of lines in the list.
This parameter may be zero, indicating that the list is
empty. If you pass -1 and a non-NULL datalist parameter,
the strings in the datalist are counted automatically. If
you pass -1 and the datalist parameter is NULL, that
indicates that you are making no change to the number of
lines in the list already attached to the object. For ease-
of-use, it is best to always place a NULL pointer at the end
of the string list, and always pass -1 for numlines. Doing
this will ensure that the internal line count changes only
when you attach a new list to the object (ie, the datalist
parameter becomes the controlling factor, and you never need
to worry about numlines).
The curindex parameter, if greater than or equal to zero,
sets a given string in the list to currently-selected
status. It can be used with a non-NULL datalist parameter
to preselect a string from the new list, or with a NULL
datalist parameter to force the given string to currently-
selected status. If -1 is passed, no change is made to the
currently-selected string. If the value passed is greater
than or equal to the number of lines in the list, it
deselects any currently-selected string. Thus, a parameter
sequence of NULL, -1, 32767, -1 effectively deselects any
currently-selected string without affecting other attributes
of the object.
The topindex parameter, if greater than or equal to zero,
sets a given string as the one to be displayed as the top
line in the window. If -1 is passed, no change is made to
the current top display line. If the value passed is
greater than or equal to the number of lines in the list,
the display is aligned to the last page of data in the list.
Passing positive values for curindex and topindex is useful
primarily when, for example, you store a string list and the
currently-selected string in a configuration file, and wish
to load the configuration from a prior run of the program
======================================================================
GemFast v1.8 Page 153
into the object.
If a positive numlines parameter is passed, and it doesn't
accurately reflect the count of lines in the list, Bad
Things will happen when you try display/use the list. If
positive curindex or topindex values are passed which are
out of range, this function basically forces them back into
range.
Source: aesfuncs\xobtscro.c
======================================================================
GemFast v1.8 Page 154
Extended Object Developer's Guide
Beta testers note: this chapter is not complete, and
anything you read here might be inaccurate.
Starting with GemFast v1.9, a support infrastructure for
extended objects is coming into being. Extended objects are
currently the major area of growth within GemFast. While I
encourage everyone with any interest to code new extended
objects using this infrastructure, and send me the results
for inclusion in future releases, I do so with caveats:
- It takes a fairly advanced knowledge of C and object-
oriented techniques coded in C to understand and use the
growing infrastructure of support.
- The infrastructure probably isn't complete, and Big
Changes could be required in your internals, or even be
suggested by you to support your objects.
- As more of these objects come into being, we're going to
find common chunks of code showing up in all of them,
and this will lead to the creation of more common
support routines that are shared by many objects. But I
haven't yet attempted to pre-design such items,
preferring to let the process drive the design instead
of having a half-thought-out design limit the process.
- The forms library needs to be extended a bit to allow
replacement form_do() handlers, and provisions need to
be made for those handlers to be able to cope with
extended objects. In particular, we need a way to feed
keystrokes to extended objects through the ub_touch
vector.
(Need a lot more words here.)
======================================================================
GemFast v1.8 Page 155
void xob_draw(OBJECT *ptree, short object, short depth,
GRECT *cliprect)
______________________________________________________________________
Summary: Object drawing module callable from supervisor mode.
Input: The ptree parameter is a pointer to the object tree to be
drawn.
The object parameter is the index of the object to start
drawing at.
The depth parameter is the number of levels of children of
the starting object which are to be drawn.
The cliprect parameter is a pointer to the clipping
rectangle for the drawing.
Returns: Nothing.
See Also:
Details: This function is a limited implementation of objc_draw().
It uses only VDI calls to render common GEM objects, so it
can be called from supervisor mode, or from within a
G_USERDEF drawing routine which the AES has called, without
the reentrancy problems encountered with the normal
objc_draw() function.
This function allows you to implement a G_USERDEF object
which is a conglomerate of standard GEM objects, without
needing to write custom rendering code.
These types of objects can be drawn by this function:
G_BOX G_IBOX G_BOXCHAR
G_TEXT G_BOXTEXT
G_TITLE G_STRING G_RSTRING
G_BUTTON G_USERDEF
The G_RSTRING object is a "replace string". It is similar
to a G_BOXTEXT with no border; the new string completely
erases any existing string, even if the new string is
shorter. The G_RSTRING type can only be used with this
function, objc_draw() can't handle it.
This function can also render the following object states:
SELECTED OUTLINED DISABLED
Other ob_state values are ignored. The new TOS 4.x 3D
visual effects are NOT implemented by this function.
======================================================================
GemFast v1.8 Page 156
In my experience so far, extended objects tend to be made up
of BOX, BOXCHAR, TEXT, and STRING objects, and generally
only the SELECTED and DISABLED states are needed.
This function behaves exactly like objc_draw() in all
respects other than the limitation of objects and states it
can render. IE, the HIDETREE flag is honored, and objects
and states are rendered in the same order as GEM does it.
While G_USERDEF is on the list, I have never tried to embed
a userdef object within another userdef object. A nested
userdef object would have to be a passive one, at the very
least, at this point.
Source: aesfuncs\xob_draw.c
======================================================================
GemFast v1.8 Page 157
void xob_transform(OBJECT *ptree, short object, XUSERBLK *pblk,
XUB_DRAWFUNC *pdraw, XUB_TOUCHFUNC *ptouch,
long xub_size);
______________________________________________________________________
Summary: Transforms a system-defined object into a GemFast-defined
extended G_USERDEF object.
Input: The ptree parameter is a pointer to the object tree holding
the object to be transformed.
The object parameter is the index of the object which is to
be transformed.
The pblk parameter is a pointer to an XUSERBLK structure
that will be attached to the object by this function.
The pdraw parameter is a pointer to the function which
renders the object during objc_draw() processing. This must
not be NULL.
The ptouch parameter is a pointer to the function which
handles clicks upon the object during dialog processing. If
this is NULL, a passive object is created which does not
respond to clicks.
The xub_size parameter is the size of the data structure
pointed to by pblk. If 0L is passed, sizeof(XUSERBLK) is
assumed internally.
Returns: Nothing.
See Also:
Details: If you think up a new type of graphics object, or you want
to change the appearance of a standard object, GEM provides
the G_USERDEF object type to help you out. With a G_USERDEF
object, the ob_spec field is a pointer to a USERBLK
structure. The USERBLK contains a pointer to a function
that draws the object, and a 4-byte field containing
application-specific info. When the AES is processing an
objc_draw() call, it calls your drawing function for any
G_USERDEF objects it finds.
If you want to transform a standard object into a G_USERDEF
object so that you can draw it differently, you have to
change the ob_type field and ob_spec field in the original
object -- six bytes of information. But the USERBLK
structure gives you only four bytes to store application-
specific info, so you can't preserve both the original
ob_type and ob_spec in the USERBLK.
An XUSERBLK structure provides additional space for you to
store things in. The first field is still a pointer to the
======================================================================
GemFast v1.8 Page 158
drawing routine, for GEM compatibility. The second field
(where application data goes in a regular USERBLK) is a
pointer to the XUSERBLK itself. The fact that the
application data field points back to the XUSERBLK itself is
the key used by GemFast internals to recognize a GemFast-
supported extended object.
To transform an object, allocate an XUSERBLK structure, and
call this function, passing pointers to the XUSERBLK, the
original object, and your custom drawing routine. This
function copies the original object's ob_type and ob_spec
into the XUSERBLK. It then changes the original object's
ob_type and ob_spec, making it a G_USERDEF object. It also
sets up the ub_code and ub_self fields of the XUSERBLK. If
you want to store some of your own data in the XUSERBLK's
userflags or userdata fields, you can do so either before or
after calling this function; this function doesn't touch
those fields in the XUSERBLK.
If the original object has a non-zero value in the extended
object type (upper byte of ob_type), this function preserves
that info in the original object, and does not copy that
part of the ob_type to the XUSERBLK.
Other GemFast functions understand extended G_USERDEF
objects set up by this function. For example, if you have a
button object, and you transform it into an extended
G_USERDEF so that it gets drawn differently, the pointer to
the button string is moved from the original ob_spec field
to the XUSERBLK structure. But, the rsc_sstrings() and
rsc_gstrings() functions will still get or set the string
pointer correctly. (IE, they'll work with the pointer in
the XUSERBLK rather than incorrectly disturbing the object's
ob_spec pointer.)
Source: aesfuncs\xobxform.c
======================================================================
GemFast v1.8 Page 159